Search code examples
watchkitapple-watchwatchosapple-watch-complicationclockkit

watchOS - Show realtime departure data on complication


I have an public transport app with realtime departure data for trains. I would like to add a complication that shows the departure time of the next train.

Is it possible to show (or refresh) realtime data on a complication? For example, showing "3 min. to station X." The data could change every minute, based on info that comes from the public transport API.

How should I accomplish this on watchOS 2 or watchOS 3?

I know the ETA app shows travel times in a complication, but I'm not sure how they achieve that.


Solution

  • Are realtime updates possible?

    • Complications aren't designed to show realtime data. Frequent updates can affect energy efficiency and impact the battery (on both watch and phone).

      To minimize power usage, ClockKit asks you to provide as much data as you have available and then caches the data and renders it when needed.

    • While there is no fixed number of times a complication timeline can be reloaded, the complication data source is subject to a daily execution time budget.

      If your app’s data changes frequently, it might be difficult to provide enough data to display in a complication. Worse, if you refresh your complication data too frequently, you may exceed your execution time budget and your complication might not be updated until the following day.

    • Once the daily budget is exhausted, calls to reloadTimeline (and extendTimeline) do nothing.

      If your complication has already exceeded its allotted daily budget for execution time, calls to this method do nothing. Call this method sparingly.

    How can a complication display relative times?

    • You can use a CLKRelativeDateTextProvider to create a formatted relative time that can change on a minute-by-minute basis.

      A CLKRelativeDateTextProvider object creates a formatted string that conveys the difference in time between the current date and a date that you specify. You use a relative date text provider to implement timers or other relative time values in an efficient way. Instead of using multiple timeline entries to replicate a countdown timer, create a single timeline entry with a relative date text provider. When the user views the clock face, ClockKit automatically updates the relative time value in your complication, providing up-to-date time information.

    How could a complication be frequently updated?

    • You could use a complication push update (either from a remote server, or locally from the phone in iOS 10).

      There is a limit of 50 complication push updates per day.

    • You could fetch data on the phone and use transferCurrentComplicationUserInfo.

      In watchOS 2, this was only subject to the daily budget. In watchOS 3, this is now limited to 50 transfers per day.

      See Is transferCurrentComplicationUserInfo more suitable for complication update? for more details.

    • In watchOS 2, you could use getNextRequestedUpdateDate to schedule the next time to update your complication.

      This can't occur more often than every ten minutes.

      Note that watchOS 3 apps should be upgraded to use background refresh app tasks. The main benefit is that background tasks would be able to do more than merely update your complication. They can also handle fetching data, updating your model once the data arrives, as well as updating your dock snapshot.

    • Finally, you can schedule a manual update. In watchOS 3, the recommended way to do this would via a background refresh app task.

      The task budget permits 4 tasks per hour. See scheduleBackgroundRefresh for more details.

      Note that background refresh app tasks must not use more than 10% CPU.

    Recommended WWDC 2016 sessions

    As mentioned in the talks, you should schedule your updates around the times when they would be needed.

    For your use case, examples would be only when public transit is running, and only when the regularly scheduled departure times would be affected by a delay.

    Apple sample code

    Apple provides WatchBackgroundRefresh sample code demonstrating how to use WKRefreshBackgroundTask to update WatchKit apps in the background.

    To update any active complication within a background task, you would simply add code to reload (or extend) the timeline:

    let complicationServer = CLKComplicationServer.sharedInstance()
    
    for complication in activeComplications {
        complicationServer.reloadTimelineForComplication(complication)
    }