How to implement handleUserActivity in WatchOS in SwiftUI?

Viewed 167

I've passed to my complicationDescriptors a userInfo dictionary that includes the names of my complications so I can be notified of which complication the user tapped on and launch them to that View. I'm using the new @App and @WKExtensionDelegateAdaptor for other reasons, so I have access to handleUserActivity in my extensionDelegate and can unpack the source of the complication tap, but how do I launch them to a specific view in SwiftUI? handleUserActivity seems to be set up to work with WKInterfaceControllers?

class ExtensionDelegate: NSObject, WKExtensionDelegate {

    let defaults = UserDefaults.standard
    
    func applicationDidFinishLaunching() {
        //print("ApplicationDidFinishLanching called")
        
        scheduleNextReload()
        
    }
    
    
    func applicationWillResignActive() {
        //print("applicationWillResignActive called")
    }
    
    func handleUserActivity(_ userInfo: [AnyHashable : Any]?) {
        
        if let complication = userInfo?[TrackerConstants.complicationUserTappedKey] as? String {
            
            if complication == TrackerConstants.recoveryDescriptorKey {
                //What now?
            } else if complication == TrackerConstants.exertionDescriptorKey {
                //What now?
            }
        }
        
    }
1 Answers

I managed to update my view according to the tapped complication userInfo by using notifications, inspired by this answer.

First declare a notification name:

extension Notification.Name {
    static let complicationTapped = Notification.Name("complicationTapped")
}

In your ExtensionDelegate:

func handleUserActivity(_ userInfo: [AnyHashable : Any]?) {
    if let complication = userInfo?[TrackerConstants.complicationUserTappedKey] as? String {
        NotificationCenter.default.post(
            name: Notification.Name.complicationTapped,
            object: complication
        )
    }   
}

Finally in your view:

struct ContentView: View {
    @State private var activeComplication: String? = nil

    var body: some View {
        NavigationView { // or TabView, etc
        // Your content with NavigationLinks
        }
        .onReceive(NotificationCenter.default.publisher(
            for: Notification.Name.complicationTapped
        )) { output in
            self.activeComplication = output.object as? String
        }
    }
}

For more information on how to activate a view from here, see Programmatic navigation in SwiftUI

Related