29

Been looking around for an answer but everything seems vague or unclear.

Anyways, just want to know what the purpose of the function:

widgetPerformUpdateWithCompletionHandler

does in the today widget.

According to Apple:

This method is called to give a widget an opportunity to update its contents and redraw its view prior to an operation such as a snapshot. When the widget is finished updating its contents (and redrawing, if necessary), the widget should call the completion handler block, passing the appropriate NCUpdateResult value.

When does the snapshot ever happen? Whenever I debug the extension, widgetPerformUpdateWithCompletionHandler always gets called after loadView. So what is the purpose of explicitly reloading information in this method when I already load the information in loadView?


According to this website: http://www.karlmonaghan.com/tag/today-widget/

In the TodayViewController, there are two places that need to load data from the network – when the widget is created and when widgetPerformUpdateWithCompletionHandler is called. For the former, I load posts in viewDidLoad, so that they should be ready by the time the widget displays. When iOS thinks the widget will be displayed to the user after it has been first displayed, widgetPerformUpdateWithCompletionHandler is called giving the widget a chance to update the posts displayed.

Same question as above.

Andrew
  • 15,357
  • 6
  • 66
  • 101
ktzhang
  • 4,069
  • 2
  • 19
  • 18
  • cool just realised karl monaghan actually found this question – ktzhang Aug 29 '14 at 15:59
  • From http://www.appcoda.com/app-extension-programming-today/ The system takes a snapshot of the widget and periodically, will try to update it. If it updates successfully, the function calls the system-provided completion block with the NCUpdateResult.NewData enumeration. If the update wasn’t successful, then the existing snapshot is used. – onmyway133 Nov 13 '14 at 05:19

1 Answers1

12

A widget is not created every time you view the notification center so loadView won't be called every time it is displayed. The notification center instead calls widgetPerformUpdateWithCompletionHandler when it thinks the widget information needs to be updated. From my own debugging it does look like that when the widget is initially created widgetPerformUpdateWithCompletionHandler is called nearly straight away so you could just do all the loading in there but Apple recommends you start the loading process as early in the life cycle as possible.

If the information your widget displays never changes, then you don't have to do anything in widgetPerformUpdateWithCompletionHandler.

Karl Monaghan
  • 880
  • 9
  • 14
  • 2
    should I update information outside of widgetPerformUpdateWithCompletionHandler? and from my debugging it looks like loadView is called every time the widget is displayed... so basically whenever widgetPerformUpdateWithCompletionHandler is called, loadView is also called so there is really no point in updating information in widgetPerformUpdateWithCompletionHandler then. – ktzhang Aug 13 '14 at 16:57
  • 15
    From what I can tell, not only is loadView called every time the widget is displayed, the widget is *fully instantiated* every time it's displayed. – John Scalo Aug 17 '14 at 22:12
  • My suspicion right now is that because this is all in beta, the widget is recreated every time but as we get closer to the GM we'll see the behaviour that they're claiming in the docs and the widget will persist in the background. – Karl Monaghan Aug 18 '14 at 12:56
  • 5
    As of 2014-09-05 Xcode 6 beta 7 still fires awakeFromNib every time the view is shown, even if scrolled off screen but Today sheet still visible. Would like to know how it'll actually work <@Apple>. – Chris Paveglio Sep 05 '14 at 13:50
  • 8
    The release notes for iOS 8.1 beta clarify it a bit: The schedule and intended use of widgetPerformUpdateWithCompletionHandler: is intended as a convenient home for all data/model update logic. If implemented, the system will call at opportune times for the widget to update its state, both when Notification Center is visible, as well as in the background. An implementation is required to enable background updates. It’s expected that the widget will perform the work to update asynchronously and off the main thread as much as possible. – Karl Monaghan Sep 30 '14 at 10:52
  • Indeed, when I launch a widget from Xcode, I observe that the widget in fully instantiated each time the widget appears on screen. Did you guys tested if it's the same in the real world? Or if Apple does apply the principles they describe in release notes? – Aurelien Porte Oct 02 '14 at 12:24
  • 2
    I have observed that on 8.0.2, Xcode 6.1 (6A1046a), on iPhone 5 (device, not simulator), the widget is being instantiated, loadView, viewDidLayoutSubviews, viewWillAppear, and viewDidAppear are all called every time the Notification Center is opened. When scrolling the widgets, I see ViewWillAppear and ViewDidAppear being called. I have yet to observe widgetPerformUpdateWithCompletionHandler being called. Leaving the notification center open for an extended period (15 minutes or so), leaving it closed (again, 15 minutes or so); in neither case does this method ever get called in my testing. – christopherdrum Oct 17 '14 at 07:42
  • 2
    How could I detect that the widget/Today Extension/Notification Centre is being viewed or has been called? I would like to do a particular task as soon as the user pulls out the Notification Centre. – Abushawish Nov 17 '14 at 19:11
  • 1
    is there a way to force this bloddy handler to be called every time? widgetPerformUpdateWithCompletionHandler – Sam B Dec 28 '14 at 22:28
  • How should one know if the content did change, when the whole extension is newly initiated on a snapshot or when the notification center is opened? How would you compare the new content with what was visible in the previous snapshot? I went that far to store the current state in Core Data just to stumble over the problem, that there seems to be no way to figure out if the widget previously was empty (e.g. first startup / system restart). If then there was no difference in my Core Data representation and the current state and I return `NoData` the widget ends up empty. Anyone solved this? – udondan Jan 25 '15 at 10:50
  • 1
    I made another test. If there was anyone in doubt if the extension is newly initiated: The PID changes with every snapshot or refresh. – udondan Jan 25 '15 at 11:05
  • 1
    Does someone knows if widgetPerformUpdateWithCompletionHandler:is also called when a significant time change has happened (i.e. time zone change or date has changed)? – valeCocoa Sep 13 '18 at 21:55