iosswiftwatchkitwatchos-3clockkit

Can't get Apple Watch complication to update in WatchOS 3


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()
    }
}

Solution

  • 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.