What is the flow for updating complication data for Apple Watch?

大憨熊 提交于 2019-11-28 04:11:46

The flow for a complication refresh that is being done on a time interval follows this sequence:

  • iOS calls your function requestedUpdateDidBegin() or requestedUpdateBudgetExhausted() (If your budget is exhausted nothing you do will cause an update until you're given more execution time.)
  • Inside of requestedUpdateDidBegin() you have to call reloadTimelineForComplication() or extendTimelineForComplication() to specify which of your complications you want reloaded or to have data added to. If you don't do this, nothing happens!
  • Depending on if you called reload or extend, iOS makes calls to one or both of getCurrentTimelineEntryForComplication() and getTimelineEntriesForComplication()
  • Irrespective of whether or not you updated your complication, iOS calls getNextRequestedUpdateDateWithHandler() to find out when you next want the above steps to repeat.

Note: the last two steps don't necessarily have to happen in that order.

The process works this way so that iOS doesn't ask you to repeatedly regenerate the same data. It gives you a chance in requestedUpdateDidBegin() to decide if your complication needs updating. If it doesn't, your code should just return. (This reduces your complication's execution time and helps avoid iOS from cutting off your app from further updates for having used its daily budget). But if you do have new data, you need to tell iOS by calling reloadTimelineForComplication() or extendTimelineForComplication()

From what I can tell, everything you've written there looks good other than you weren't requesting a reload or extend inside requestedUpdateDidBegin(). It's possible for your complication to be visible on the watch face in more than one position, and for different templates to have different display behaviours, so you have to invalidate all of them. Here is what my code looks like:

func requestedUpdateDidBegin() {

    //Not shown: decide if you actually need to update your complication.
    //If you do, execute the following code:

    let server=CLKComplicationServer.sharedInstance()

    for comp in (server.activeComplications) {
        server.reloadTimelineForComplication(comp)
    }
}

Note that besides time intervals that there are other ways to initiate refreshes including push alerts, executing reloads when your watch app runs, or using the Watch Connectivity framework with a WCSession to have your phone app send update data to be displayed immediately via transferCurrentComplicationUserInfo(). See Updating Your Complication Data in Apple's docs for more info.

I've had success in the simulator testing update intervals as short as ten minutes. You probably shouldn't update that frequently on the real watch due to the execution time budget, but this will allow you to test your code without waiting 12 hours.

El Tea's answer goes into detail on how to update a complication for watchOS 2.

In watchOS 3, the recommended way to keep your complication up to date involves using background refresh app tasks. You can use a series of background tasks to schedule and handle your app extension being woken in the background to:

  • Fetch new data

  • update your model once the data arrives,
  • update your complication (by reloading or extending the timeline) to display the new data available from the model, and finally
  • update your app's dock snapshot to show the data on the dock

This is much more functional as well as energy efficient, as it does not use any of your complication's daily execution budget to fetch data or update the model.

It also avoids any complexity from unadvised approaches which tried to asynchronously fetch data in a complication datasource that was only ever meant to immediately respond to requests.

I've provided further information, as well as links to WWDC videos and sample code, in a different answer.

To sum up the change for watchOS 3

Use scheduled background tasks instead of getNextRequestedUpdateDateWithHandler().

Reload or extend your timeline in an app task, instead of within requestedUpdateDidBegin().

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!