Reputation: 401
I'm making a home screen widget for iOS 14 using the new WidgetKit and I want my widget timeline to refresh when the user responds to a notification.
This is what my code looks like currently:
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
if response.actionIdentifier == "actionIdentifier" {
print("notification response received")
WidgetCenter.shared.reloadAllTimelines()
}
completionHandler()
}
But my widget is not updated when the user responds to the notification. The print statement gets printed, so I know my app is receiving the response. The widget also gets refreshed when I call reloadAllTimeLines()
anywhere else in my app, so I'm sure my widget extension is implemented correctly. But it's not updating in the above scenario.
Is this a bug or am I doing something wrong? Or is there another way to reload a widget timeline after the user responds to a notification.
Upvotes: 18
Views: 13540
Reputation: 55785
tldr; Reloading your widgets while the app is in the background does seem to work, however, it may not update immediately.
I encountered this recently and added logging to determine what's going on. If curious I did this by adding NSLog
everywhere relevant, replicating the issue, collecting a sysdiagnose, and examining the system_logs. I tested this scenario which seems to be the most extreme: trigger the notification action from my Apple Watch with the iPhone locked, in low power mode, with the app not open in the background, and 3 widgets added to the Home Screen.
What I found is the app was launched, the notification action was processed, and reloadAllTimelines()
was triggered as expected. But getTimelines
in the widget was not called - not until about 24 minutes later! So it will update eventually. And note this was not due to my timeline reload policy - I have that set to only refresh once a day at midnight.
iOS is surely trying to be smart about when it'll process reload requests to preserve battery life etc.
Upvotes: 4
Reputation: 401
This seems to be fixed in iOS 14 beta 2. The widget now correctly updates when refreshAllTimelines() is called from the notification response.
Upvotes: 12
Reputation: 49
Try calling that under Dispatch Main, or try calling it with a delay of, to test, say 2 seconds.
I am calling the same on SwiftUI's List as
let listArray = ["Item1", "Item2", "Item3"]
List(listArray) { listObject in
Button(action: {
WidgetCenter.shared.reloadAllTimelines()
}) {
HStack {
Text(listObject)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .leading)
.padding()
}
}
}
And it's working like charm.
Upvotes: 4