I use AppIntent to trigger a widget refresh, Appint is used on Button or Toggle,as follows
var isAudibleArming = false struct SoundAlarmIntent: AppIntent { static var title: LocalizedStringResource = "SoundAlarmIntent" func perform() async throws -> some IntentResult { isAudibleArming = true return .result() } }
func timeline( for configuration: DynamicIntentWidgetPersonIntent, in context: Context ) async -> Timeline<Entry> { var entries: [Entry] = [] let currentDate = Date() let entry = Entry(person: person(for: configuration)) entries.append(entry)
if isAudibleArming {
let entry2 = Entry(person: Person(name: "Friend4", dateOfBirth: currentDate.adding(.second, value: 6)))
entries.append(entry2)
}
return .init(entries: entries, policy: .never)
}
The timeline function fires, with entry corresponding to view1 and entry2 corresponding to view2. I expect to show view1 immediately and view2 6 seconds later. You get the correct response on iOS17. But the 6 second delay function on the discovery code in iOS18.2 takes effect immediately, view1 flashes, view2 appears immediately instead of waiting 6 seconds to appear.
This is not how widgets work. The timeline is a series of snapshots of data, i.e. what should appear at the first date, then the second date, then the third etc. Your widget doesn't really run any code.
You do not need a .init()
method in your Entry
struct, and I suspect your issue with it immediately flashing to the next timeline entry is because your Entry
struct sets the date
to .now
for every entry.
That struct should look something like this:
struct EventEntry: TimelineEntry {
public let date: Date
let configuration: DynamicIntentWidgetPersonIntent
let person: Person
let type: FriendType
}
Then in the timeline
you create a series of entries that reflect what should happen at various times.
And note that you're limited to about 72 updates per day, and widgets aren't really deigned to update every few seconds, so adding 3 or 6 seconds to a date isn't going to guarantee that your widget gets updated when you think it will.
Once you have a timeline set up you can see it in the preview in Xcode with something like this:
#Preview(as: .systemSmall) {
WidgetExtension()
} timeline: {
let person = //some Person object
let currentDate: Date = Date.now
for minuteOffset in stride(from: 0, to: (24 * 60), by: 20) { // every 20 mins for one day = 72 entries
let entryDate = Calendar.current.date(byAdding: .minute, value: minuteOffset, to: currentDate, wrappingComponents: false)!
EventEntry(date: entryDate, configuration: configuration, person: person, type: .whatever))
}
}
Scroll through the timeline at the bottom of the preview window to see how your widget changes over time.
I have no idea how you're using the .init
method and this whole FriendType
thing, but I don't think it's working how you think it's working.