Mathias Halén
Mathias Halén

Reputation: 145

How do I refresh WatchApp complications

So I'm trying to update headerTextProvider: every second with a Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { timer in

I guess that this is not the right way of doing this?

    // MY STUFF HERE
    //----------------------------------------------------------------------------------------------------
    func getCurrentTimelineEntry(for complication: CLKComplication,
                                 withHandler handler: @escaping (CLKComplicationTimelineEntry?) -> Void) {

        @ObservedObject var service = Service()
        print("-------------------->>>>>>>>>> \(service.currentTime)")
        let date = Date()
        //let currentTime = service.currentTime
        let title = service.title
        let time = service.time

        var template: CLKComplicationTemplate!
        let line1 = CLKSimpleTextProvider(text:title)
        let line2 = CLKSimpleTextProvider(text:time)
        //let line3 = CLKSimpleTextProvider(text:currentTime)

        if complication.family == .modularLarge {
            template = CLKComplicationTemplateModularLargeStandardBody(headerTextProvider: line1, body1TextProvider: line2)
            let entry = CLKComplicationTimelineEntry(date: date, complicationTemplate: template)
            handler(entry)
        }
        else{
            handler(nil)
        }
    }

The Whole Code

//
//  ComplicationController.swift
//  WatchApp WatchKit Extension
//
//  Created by Mathias Halén on 2021-06-22.
//  Copyright © 2021 Mathias Halén. All rights reserved.
//

import ClockKit
import SwiftUI


class ComplicationController: NSObject, CLKComplicationDataSource {
    final class Service: ObservableObject{
        static let sharedInstance1 = Service()
        @Published var currentTime = " first time"
        @Published var title = "Hello"
        @Published var time = "World"
        
        init() {
            Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { timer in
                print("----------> WatchOS -> ComplicationController \(Date())")
                self.currentTime = GlobalVaribles.sharedInstance.currentTime
                self.title = GlobalVaribles.sharedInstance.title
                self.time = GlobalVaribles.sharedInstance.time
            }
        }
    }
    
    // MARK: - Complication Configuration
    func getComplicationDescriptors(handler: @escaping ([CLKComplicationDescriptor]) -> Void) {
        
        let descriptors = [
            CLKComplicationDescriptor(identifier: "complication",
                                      displayName: "Test 2",
                                      supportedFamilies: CLKComplicationFamily.allCases)
            // Multiple complication support can be added here with more descriptors
        ]
        
        // Call the handler with the currently supported complication descriptors
        handler(descriptors)
    }
    func handleSharedComplicationDescriptors(_ complicationDescriptors: [CLKComplicationDescriptor]) {
        // Do any necessary work to support these newly shared complication descriptors
    }
    // MARK: - Timeline Configuration
    func getTimelineEndDate(for complication: CLKComplication, withHandler handler: @escaping (Date?) -> Void) {
        // Call the handler with the last entry date you can currently provide or nil if you can't support future timelines
        let currentDate = Date()
        handler(currentDate)
    }
    func getPrivacyBehavior(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationPrivacyBehavior) -> Void) {
        // Call the handler with your desired behavior when the device is locked
        handler(.showOnLockScreen)
    }
    func getLocalizableSampleTemplate(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTemplate?) -> Void) {
        // This method will be called once per supported complication, and the results will be cached
        handler(nil)
    }
    // MY STUFF HERE
    //----------------------------------------------------------------------------------------------------
    func getCurrentTimelineEntry(for complication: CLKComplication,
                                 withHandler handler: @escaping (CLKComplicationTimelineEntry?) -> Void) {
        
        @ObservedObject var service = Service()
        print("-------------------->>>>>>>>>> \(service.currentTime)")
        let date = Date()
        //let currentTime = service.currentTime
        let title = service.title
        let time = service.time
        
        var template: CLKComplicationTemplate!
        let line1 = CLKSimpleTextProvider(text:title)
        let line2 = CLKSimpleTextProvider(text:time)
        //let line3 = CLKSimpleTextProvider(text:currentTime)
        
        if complication.family == .modularLarge {
            template = CLKComplicationTemplateModularLargeStandardBody(headerTextProvider: line1, body1TextProvider: line2)
            let entry = CLKComplicationTimelineEntry(date: date, complicationTemplate: template)
            handler(entry)
        }
        else{
            handler(nil)
        }
    }
   
}

Upvotes: 0

Views: 1136

Answers (1)

Paulw11
Paulw11

Reputation: 114783

As a rule, you don't "push" timeline entries to your complication. You supply timeline entries when ClockKit requests them.

You can use reloadTimeline and extendTimeline to trigger a request from ClockKit, but you would normally only use this periodically; Say when user interaction causes your app to load new data or perhaps based on a scheduled refresh task.

See Keeping Your Complications Up to Date for more details.

Using a Timer isn't really an approach that makes sense; The Timer will only fire when your watch app is in the foreground, and if it is in the foreground then your complication isn't being show.

What you can do is implement getTimelineEndDate and getTimelineEntries in your data source; then when your data source is asked for entries you can supply future entries for the complication to show.

First, supply .distantFuture for the end date, indicating that your complication can provide data indefinitely.

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

Second, supply a series of time line entries, one for each of the next 3600 seconds, say.

func getTimelineEntries(for complication: CLKComplication, 
                           after date: Date, 
                           limit: Int, 
                     withHandler handler: @escaping ([CLKComplicationTimelineEntry]?) -> Void) {

    guard complication.family == .modularLarge else {
        handler(nil)
        return
    }

    let now = Date()
    var entries = [CLKComplicationTimelineEntry]()
    let line1 = CLKSimpleTextProvider(text:title)
    for i in 0..<3600 {
        let template = CLKComplicationTemplateModularLargeStandardBody(headerTextProvider: line1, body1TextProvider: line2)
        let line2 = CLKSimpleTextProvider(text:"\(i)")
        let entry = CLKComplicationTimelineEntry(date: date.addingTimeInterval(Double(i)), complicationTemplate: template)
            entries.append(entry)
    }
    completion(entries)
}

Upvotes: 1

Related Questions