I am finding that my Notification Center widget does not reload very often. Because of this, out of date data being presented. I have not been able to find a way to get the widget to refresh every time I open the Today view. I have seen apps such as NBA Gametime that are able to update every time I pull down to see the widget.
How can I get this functionality in my app?
Based on my own experimentation and also reports in this SO thread, it appears that the TodayViewController.viewDidLoad() function gets called every time the Today/Notifications area gets opened. More specifically, #Karl Monaghan reported in a comment that the iOS 8.1 release notes have the following to say:
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.
So, to answer your question:
I don't think we'll ever really know how often the widgetPerformUpdateWithCompletionHandler method gets called, and I think Apple prefers it that way
The viewDidLoad function does get called every time the widget is displayed, so it's possible that you could put a call to the update function inside of that method. Or you could just put whatever updates you need to be shown in the widget inside of that function, although I don't know what kind of impact that will have on app performance.
Hope this helps.
Update
I've also found that either one of initWithCoder or initWithNibName seems to get called every time the widget is displayed on the screen, so it's possible that you could put calls to update your widget in those files, but if I recall correctly the view is not actually instantiated at this time so it's better NOT to put your code to update your widget in these functions.
In your widgetPerformUpdateWithCompletionHandler you need to to let your widget know that it needs to update. Apple Docs
-(void)widgetPerformUpdateWithCompletionHandler:(void (^)(NCUpdateResult))completionHandler {
// Perform any setup necessary in order to update the view.
// If an error is encoutered, use NCUpdateResultFailed
// If there's no update required, use NCUpdateResultNoData
// If there's an update, use NCUpdateResultNewData
completionHandler(NCUpdateResultNewData);
}
Related
I have application with lot of view controllers and on every time when app comes from background I have to make some request to server and reinitialise some global variables. At the moment I am doing this by repeating code in every view controller in didViewLoad but I wonder is there way to this in delegate to avoid repeating on 10 places ? ( I check didFinishLuanchingWithOptions in delegate but it is called only first time not when app comes from background ).
I think you want to look at these two:
applicationDidBecomeActive
And
applicationWillEnterForeground
Check out the documentation for more details.
In my Notification Center Today Extension/Widget I need to update a portion of the UI every time Notification Center is activated. It never needs to update while Notification Center is in use, nor while it's in the background. In what method should I place that code?
viewDidLoad and viewWillAppear are both called every time it will be displayed, for example if you scroll up and down they will be called again, so that's too often.
widgetPerformUpdateWithCompletionHandler is not called at all before it's displayed for the first time it seems (at least with iOS 8.2 beta), and this method is automatically called whenever iOS feels like it to update the UI even when it's in the background which is not appropriate either.
loadView is only called a single time, never to be called again unless the widget is removed from memory. So if you open Notification Center and view the widget then dismiss Notification Center and reopen it later, it may not call that method again depending on whether or not it's been cleared from memory.
I'd just use viewDidLoad and not worry about the possibility of multiple calls. Unless the method takes a long time to run, there's no reason not to do it that way. [And if it does take a long time to run, your today extension is going to suck, so fix that.]
If for some reason you only want it to happen once, add a BOOL ivar to the class. Set it to YES in initWithCoder: Then in viewDidLoad, check that value. If it's YES, do your update and set the value to NO. If it's already NO, skip your update.
According to Apple documentation, "To help your widget look up to date, the system occasionally captures snapshots of your widget’s view. When the widget becomes visible again, the most recent snapshot is displayed until the system replaces it with a live version of the view."
What I am seeing, however, is that the snapshot is removed from screen before the live view is prepared. This results in a flash effect where the old snapshot is taken off screen, the view is blank for a split second, then the new view appears.
Is the developer responsible for making the transition between the snapshot and the live view seamless? If so, what is the strategy behind doing that? I don't see any way to directly control that transition.
I was able to mitigate the effect greatly by moving data loading to
widgetPerformUpdateWithCompletionHandler: and keeping drawing in viewWillAppear:, but I do still see a flash once every 15 (or so) opens of the Notification Center.
I had this same issue and finally figured out the issue I was having with my widget. It turns out it was related to a misunderstanding about the Widget Life Cycle on my behalf.
From the documentation I thought that the today view would keep a 'snapshot' of my widgets state until the widgetPerformUpdateWithCompletionHandler method completion handler was called with success.
This does not seem to be the case. From what I can see the 'snapshot' is just used when the Today View is animating in (when the user pulls down the notification centre). As soon as the today view is loaded and stationary your widget is loaded from scratch (inflated from xib if using) and viewDidLoad is called. At this moment you should populate you widget with cached data (not from a web request). If you don't you will see temporary data from your nib. This is what causes the flashing.
When viewDidLoad is complete widgetPerformUpdateWithCompletionHandler is called which allows you to fetch fresh data. When the fresh data is fetched you should call the completion handler and cache the data it so it can be used when the widget is loaded later on from scratch (in viewDidLoad).
A simple way to cache the data is in user defaults.
You need to be careful about your compilation handler in the
-(void)widgetPerformUpdateWithCompletionHandler:(void (^)(NCUpdateResult))completionHandler
method. What happens is that your extension probably has an error and everytime view appers it is being called again. Try to attach your extension to debugger(Debugger->Attach to Process-> your extension id) and see the result by putting some breakpoints.
I am programming an ios app and would like to save information on exit of the view. I know how to go about saving the actual information but I'm not sure where I should put the code.
In android, there are methods like onPause() where I can run the save code to capture whenever someone leaves an activity. Is there something in obj-c like that?
You can add your logic for saving the state of the view in viewWillDisappear
I guess you have not gone through the View Life Cycle, here s one nice image which has captured the view life cycle events.
Reference : http://rdkw.wordpress.com/2013/02/24/ios-uiviewcontroller-lifecycle/
every one knows that skstoreproductviewcontroller's loadproductwithparamters method need to ask app informations from web,so it load very slow,is there any method to run loadproductwithparameters in background to show the app information fast?
The information will naturally load in the background and the intention is that you call loadProductWithParameters:completionBlock: before you actually want to display the view (and you can use the completion block to either show the view or to tag the item as being available to show).