Complications locally scheduled wakeup

In the WatchConnectivity session at WWDC 2015, the speaker mentioned we can use locally scheduled wake up to get updated information using NSURLSession. However, he doesn't go in depth on where exactly we get woken up. It seems like this wake up is scheduled using the getNextRequestedUpdateDateWithHandler: callback, but I thought this will just call all the regular CLKComplicationDataSource callbacks as opposed to a special one that allows us to get data using NSURLSession. I was under the impression there would be a callback like application:performFetchWithCompletionHandler: where we would be able to get data from our cloud and then use ClockKit to update the Watch face. Is this not the case?


They also keep mentioning that all of these updates are budgeted but don't give any specifics. Is there a range that Apple can share with us?

The specifics are provided in the WatchConnectivty Session. Budgeting will allow for appoximately 2 updates per hour of the watch complication, but those could all be exaused in as little time as you choose.


As for details on how to setup the locally scheduled wake, it does seem that at some point it will be part of the watchkit extention delegate and might have something to do with the getuseractivity method since the CLKComplicationDataSource passes a date key to the getuseractivity dictionary at "launch" but it doesn't go into specifics on what a "launch" means.


My best guess is that the required SDK methods are still in the pipeline and not currently included in betas.

I thought the 2 / hour was only for Pushes? I've been testing with it and I've definitely gone over 2 / hour, but that is just when I tell the complication to refresh as opposed to having the locally scheduled wake up.

The way it was spoken in the WatchConnectivity session made is sound like the same system used for remote notification will be used for local notifications and thus fall under the same limit.


Note: 2 per hour is over a 24 hour period, so really if you consider that the watch is likely charging for 7 hours a day you really can update the watch about three times an hour. Which in all honesty is probably more than enough, I doubt anyone is looking at their wrist every 5 minutes and if they are they need to be within an app and not on the clock face.

The entry point when your WatchKit extension is woken for a complication update is the same no matter how you get your data. In that entry point you should then use the NSURLSession APIs to receive any previously requested background data and/or fire off a new request.


As for budgetting; the WWDC session gave guidance that when using the 'pushed' approached (using PushKit and WatchConnectivity's transferCurrentComplicationUserInfo) you could count on roughly 1-2 per hour over a 24 hour period. This could be more or less depending on how efficient (CPU usage, runtime duration, etc) both your iOS app and WatchKit are when updating the complication.

If you are not using the pushed approach, but a locally scheduled update combined with a direct request to the cloud the factors involved will be http payload size, the amount of time and processing your extension does in response to the request, etc.

If I'm following you correctly, you're saying in one of the data source methods we should be firing off a background NSURLSession? Then when that background request is done, it will re-wake up our extension if it's been terminated so we can tell ClockKit if anything changed?


If so, in which data source method am I supposed to fire off the background NSURLSession?

What is the entry point?

Please clarify this entry point.

In seed 3 ClockKit's CLKComplicationDataSource protocol has these new optional delegate methods:

/// This method will be called when you are woken due to a requested update. If your complication data has changed you can
/// then call -reloadTimelineForComplication: or -extendTimelineForComplication: to trigger an update.
@optional
- (void)requestedUpdateDidBegin;


/// This method will be called when we would normally wake you for a requested update but you are out of budget. You can can
/// trigger one more update at this point (by calling -reloadTimelineForComplication: or -extendTimelineForComplication:) but
/// this will be the last time you will be woken until your budget is replenished.
@optional
- (void)requestedUpdateBudgetExhausted;

which would be the "entry points" to use. You can read more about them in the ClockKit framework reference.

I have another question about budgeting:


At the end of WWDC session

Creating Complications with ClockKit

there is a slide with 3 bullet points on how to update complications:


- Whenever extension runs

- When Watch app runs (Budgeted)

- Locally scheduled wake iPhone initiated wake (Budgeted)


So if I understand correctly, I can call reloadTimelineForComplication: as many times as I want when the WatchKit app is in the foreground accordind to first bullet point? Or is this call budgeted no mater what?


Best,


Matic



re: I can call reloadTimelineForComplication: as many times as I want when the WatchKit app is in the foreground

Yes, that is correct, though unless the content for the current timeline entry is changing rapidly you'd probably want to call extendTimeline instead most of the time. Also, I believe ClockKit will batch up the requests to change the reload/extend the timeline if your extension requests them in rapid succession. Example: your code calls reloadTimelineForComplication 5 times in the span of 1 second, ClockKit might only kick off one timeline reload.

Complications locally scheduled wakeup
 
 
Q