Search code examples
iosswiftswiftuiios14widgetkit

Detect app launch from WidgetKit widget extension


Tapping a WidgetKit widget automatically launches its parent application. How can I detect if my application was launched from its WidgetKit widget extension?

I'm unable to find any documentation on capturing this in the applications AppDelegate and/or SceneDelegate.


Solution

  • To detect an app launch from a WidgetKit widget extension where the parent application supports scenes you'll need to implement scene(_:openURLContexts:), for launching from a background state, and scene(_:willConnectTo:options:), for launching from a cold state, in your parent application's SceneDelegate. Also, add widgetURL(_:) to your widget's view.

    Widget's View:

    struct WidgetEntryView: View {
        
        var entry: SimpleEntry
        
        private static let deeplinkURL: URL = URL(string: "widget-deeplink://")!
    
        var body: some View {
            Text(entry.date, style: .time)
                .widgetURL(WidgetEntryView.deeplinkURL)
        }
        
    }
    

    Parent application's SceneDelegate:

    // App launched
    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let _: UIWindowScene = scene as? UIWindowScene else { return }
        maybeOpenedFromWidget(urlContexts: connectionOptions.urlContexts)
    }
    
    // App opened from background
    func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
        maybeOpenedFromWidget(urlContexts: URLContexts)
    }
    
    private func maybeOpenedFromWidget(urlContexts: Set<UIOpenURLContext>) {
        guard let _: UIOpenURLContext = urlContexts.first(where: { $0.url.scheme == "widget-deeplink" }) else { return }
        print("🚀 Launched from widget")
    }