I've read the documentation Apple have provided on the "Creating a Widget Extension" page, but it doesn't seem to match what's happening.
My app lets users create events, and the widget should let users choose an event to display. You can have multiple widgets, all displaying different events.
When the user installs the app for the first time and launches it, there are no events, so trying to add a widget will display some preview data (a fake event) to give the user an idea of what the widget will look like.
In the placeholder func I return the preview data, and it does show this fake event when you're in the preview screen (the panel with the "Add Widget" button on it). placeholder() is called twice because I'm using both systemSmall and Medium widget sizes.
getSnapshot() is then called, and the context.isPreview is true or the 'configuration' parameter is nil so I return the preview data again. This works fine.
Once the user adds the widget to the Home Screen, they get a different view that tells them to edit the widget (because no event has actually been chosen yet). This is set up in both getSnapshot() and getTimeline().
So, the user sees this widget telling them to edit it and select an event, or tap it to launch the app and create an event. The user tries to edit the widget and there are no events listed. Fine. All works well so far.
The user taps the widget and adds an event in the app. They go back to the Home Screen and edit the widget. Their event is present, so they select it.
getTimeline() is called, which calls a function to get the event the user selected. This works properly and returns the correct event object for the selected event, e.g. "Paris Trip".
getTimeline() then confirms it has the event and sets up the timeline, five entries, 5 minutes apart.
But the widget on the Home Screen still displays the preview data. I can wait five minutes, an hour, a day and it will not change.
So, based on the above and the following code, how do I get the widget to actually work?
My app lets users create events, and the widget should let users choose an event to display. You can have multiple widgets, all displaying different events.
When the user installs the app for the first time and launches it, there are no events, so trying to add a widget will display some preview data (a fake event) to give the user an idea of what the widget will look like.
In the placeholder func I return the preview data, and it does show this fake event when you're in the preview screen (the panel with the "Add Widget" button on it). placeholder() is called twice because I'm using both systemSmall and Medium widget sizes.
getSnapshot() is then called, and the context.isPreview is true or the 'configuration' parameter is nil so I return the preview data again. This works fine.
Once the user adds the widget to the Home Screen, they get a different view that tells them to edit the widget (because no event has actually been chosen yet). This is set up in both getSnapshot() and getTimeline().
So, the user sees this widget telling them to edit it and select an event, or tap it to launch the app and create an event. The user tries to edit the widget and there are no events listed. Fine. All works well so far.
The user taps the widget and adds an event in the app. They go back to the Home Screen and edit the widget. Their event is present, so they select it.
getTimeline() is called, which calls a function to get the event the user selected. This works properly and returns the correct event object for the selected event, e.g. "Paris Trip".
getTimeline() then confirms it has the event and sets up the timeline, five entries, 5 minutes apart.
But the widget on the Home Screen still displays the preview data. I can wait five minutes, an hour, a day and it will not change.
So, based on the above and the following code, how do I get the widget to actually work?
Code Block swift func placeholder(in context: Context) -> EventEntry { return entryPreviewData } func getSnapshot(for configuration: DynamicEventSelectionIntent, in context: Context, completion: @escaping (EventEntry) -> Void) { var entry: EventEntry if(context.isPreview configuration.event == nil) { entry = entryPreviewData } else { EventDetail.getUpdatedEventsFromDefaults() if(EventDetail.availableEvents .isEmpty) { entry = entryNoEventsData } else { let selectedEvent = event(for: configuration) if(selectedEvent.type == kEventTypeNoEvents) { entry = entryNoEventsData } else if(selectedEvent.type == kEventTypeError) { entry = entryErrorData } else { entry = EventEntry(date: Date(), relevance: nil, event: selectedEvent) } } } completion(entry) } func getTimeline(for configuration: DynamicEventSelectionIntent, in context: Context, completion: @escaping (Timeline<EventEntry>) -> Void) { var entries: [EventEntry] = [] var timeline: Timeline<EventEntry> if(context.isPreview configuration.event == nil) { entries.append(entryNoEventsData) timeline = Timeline(entries: entries, policy: .after(Date().advanced(by: 15))) } else { let selectedEvent = event(for: configuration) if(selectedEvent.type == kEventTypeNoEvents) { /* There are no events, so return the no events data */ entries.append(entryNoEventsData) timeline = Timeline(entries: entries, policy: .after(Date().advanced(by: 15))) } else if(selectedEvent.type == kEventTypeError) { /* Received error data, so return the error data */ entries.append(entryErrorData) timeline = Timeline(entries: entries, policy: .after(Date().advanced(by: 15))) } else { var entryDate: Date = Date() for _ in 0 ..< 5 { entryDate = Calendar.current.date(byAdding: .minute, value: 5, to: entryDate)! entries.append(EventEntry(date: entryDate, relevance: relevance, event: selectedEvent)) } timeline = Timeline(entries: entries, policy: .atEnd) } } completion(timeline) }