4

I can't get the Apple Watch Complication to update/refresh in WatchOS 3. I I'm using the following code in my ComplicationController.swift file.

func getSupportedTimeTravelDirections(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTimeTravelDirections) -> Void) {
    handler([.forward])
}

func getTimelineStartDate(for complication: CLKComplication, withHandler handler: @escaping (Date?) -> Void) {
    handler(Date())
}

func getTimelineEndDate(for complication: CLKComplication, withHandler handler: @escaping (Date?) -> Void) {
    handler(Date(timeIntervalSinceNow: 60 * 30))
}

I have also tried to schedule an update from the handle background task method in the ExtensionDelegate.swift but it dosen't seem to work either.

func scheduleNextRefresh() {
    let fireDate = Date(timeIntervalSinceNow: 30 * 60)
    let userInfo = ["lastActiveDate" : Date(),
                    "reason" : "updateWeekNumber"] as Dictionary

    WKExtension.shared().scheduleBackgroundRefresh(withPreferredDate: fireDate, userInfo: userInfo as NSSecureCoding) { (error) in
        if error == nil {
            print("Succesfully updated week number")
        }
    }
}

func handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>) {
    for task: WKRefreshBackgroundTask in backgroundTasks {
        if WKExtension.shared().applicationState == .background {
            if task is WKApplicationRefreshBackgroundTask {
                print("Task received")
                scheduleNextRefresh()
            }
        }
        task.setTaskCompleted()
    }
}
user8175227
  • 43
  • 1
  • 3

1 Answers1

8

WKRefreshBackgroundTask do not update anything itself, it just allows your app to go to active state and run code (placed somewhere around print("Task received") line) that will update your complication. Remember that number of WKRefreshBackgroundTasks is limited.

Complication can be updated such way:

let server = CLKComplicationServer.sharedInstance()

// if you want to add new entries to the end of timeline
server.activeComplications?.forEach(server.extendTimeline)

// if you want to reload all the timeline, which according to snippets looks like your case
server.activeComplications?.forEach(server.reloadTimeline)

This will cause system to call getCurrentTimelineEntry(for:withHandler:) methods of your CLKComplicationDataSource, where you can prepare and return updated entries.

More about complications update in documentation. More about background tasks in WWDC16 session.

abjurato
  • 1,439
  • 11
  • 17
  • Thanks! Where is the best place to call the ```scheduleNextRefresh()``` method? I have done it in the interface controller for the watch app in the awake method. – user8175227 Jun 26 '17 at 21:50
  • generally, you want to update complication when new data arrives, so that place is a good candidate to call schedule background task from. But pay attention that completion handler of `scheduleBackgroundRefresh` is called when background refresh is *scheduled*, not executed, documentation at https://developer.apple.com/documentation/watchkit/wkextension/1650848-schedulebackgroundrefresh has an error. See here: https://stackoverflow.com/questions/41238434/when-wkextension-schedulebackgroundrefresh-is-supposed-to-call-scheduledcompleti – abjurato Jun 27 '17 at 06:10
  • This doesn't work for me - nothing changes and `getCurrentTimelineEntry(for:withHandler:)` won't get called – Kai Zheng Sep 21 '20 at 13:50