0

I'm writing a SwiftUI-based Apple Watch app with a ClockKit-based complication.

There is a need for, at certain times, the complication's timeline to be fully invalidated and re-generated from within the main Watch app. For this, I use CLKComplicationServer.reloadTimeline(for:). The trouble is that this appears to be an async method, and at some point after my code returns, the app crashes with the error message in the title.

I'm at a loss for how to debug this, since the call stack just places the error unhelpfully at the top of the root SwiftUI view, with the earlier entries in the stack being in assembly code that I can't put a breakpoint at because the addresses seem to change with each run. A Google search for the phrase "failed to call completion handler in" yields 0 results.

For this, I have the following code:

private func reloadComplication() async{
        let server = CLKComplicationServer.sharedInstance()
        let complications = await server.getActiveComplications()
        for complication in complications {
            server.reloadTimeline(for: complication)
        }
    }
extension CLKComplicationServer {

    // Safely access the server's active complications.
    @MainActor
    func getActiveComplications() async -> [CLKComplication] {
        return await withCheckedContinuation { continuation in

            // First, set up the notification.
            let center = NotificationCenter.default
            let mainQueue = OperationQueue.main
            var token: NSObjectProtocol?
            token = center.addObserver(forName: .CLKComplicationServerActiveComplicationsDidChange, object: nil, queue: mainQueue) { _ in
                center.removeObserver(token!)
                print("CDBG: Continuation resumed in addObserver closure")
                continuation.resume(returning: self.activeComplications!)
            }
            print("CDBG: Added observer with token \(String(describing: token))")

            // Then check to see if we have a valid active complications array.
            if activeComplications != nil {
                center.removeObserver(token!)
                print("Continuation resumed in activeComplications check")
                continuation.resume(returning: self.activeComplications!)
            }
        }
    }
}

The above extension was taken straight from Apple's own documentation here.

I normally call reloadComplication from a completion handler for CLLocationManager, but I tried it from a SwiftUI closure with no change.

When the method is called, I see that getActiveComplications successfully returns an array of CLKComplication, and that reloadComplication does successfully return. A little bit later, I get a hard crash with the following message in the console:

2023-03-15 18:05:33.964162-0400 TestApp WatchKit Extension[1023:1538862] [remotecomplication] Failed to call completion handler in -[CLKComplicationDataSource getLocalizableSampleTemplateForComplication:withHandler:].
2023-03-15 18:05:33.964735-0400 TestApp WatchKit Extension[1023:1538862] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Failed to call completion handler in -[CLKComplicationDataSource getLocalizableSampleTemplateForComplication:withHandler:]'
*** First throw call stack:
(0x24aa690c 0x2408e7ec 0x24b3c320 0x367d0e24 0x2407a504 0x7150ef68 0x7150de60 0x7150d6a0 0x7150d354 0x2407a504 0x367cc6cc 0x30cf848 0x30d1040 0x30dfa78 0x30df6dc 0x24a1fbb4 0x249f1204 0x24a37c9c 0x4bed4968 0x25d8c040 0x25d3c764 0x325a86d8 0x2c0fd814 0x2c0fa990 0x2b7d358 0x2b7d40c 0x324fbd24 0x6e1918c4)
libc++abi: terminating with uncaught exception of type NSException
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Failed to call completion handler in -[CLKComplicationDataSource getLocalizableSampleTemplateForComplication:withHandler:]'
terminating with uncaught exception of type NSException

Any idea what I'm doing wrong here?

tattar8
  • 11
  • 2

0 Answers0