Michał Ziobro
Michał Ziobro

Reputation: 11812

iOS 13 > Universal App Links does not work when app is killed and not in background

Any idea why starting from iOS 13 app links (universal links) this defines via Apple-App-Site-Association stopped working?

I have 2 implementations in ApplicationDelegate and in SceneDelegate. Now works only implementation in SceneDelegate and only if application is in background, if I kill app then method continueUserActivity isn't called. I have added Haptic Feedback to track this method call but it will never be invoked neither in ActivityDelegate or SceneDelegate.

// MARK: - Universal Links support
extension SceneDelegate {

    func scene(_ scene: UIScene, willContinueUserActivityWithType userActivityType: String) {
        print("[Scene] Will continue user activity: ", userActivityType)
        let generator = UINotificationFeedbackGenerator()
        generator.notificationOccurred(.success)

    }

    func scene(_ scene: UIScene, didFailToContinueUserActivityWithType userActivityType: String, error: Error) {
        print("[Scene] Did fail to continue user activity: ", userActivityType)
    }

    func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {

        print("[Scene] Application continue user activity...")

        if userActivity.activityType == NSUserActivityTypeBrowsingWeb {
            if let url = userActivity.webpageURL {
                if !present(url: url) { UIApplication.shared.open(url, options: [:]) }
            }
        }
    }

And Application Delegate case

// MARK: - Universal Links support
extension AppDelegate {

    func application(_ application: UIApplication, willContinueUserActivityWithType userActivityType: String) -> Bool {
        print("[App] Will continue user activity: ", userActivityType)
        let generator = UINotificationFeedbackGenerator()
        generator.notificationOccurred(.warning)
        return true
    }

    func application(_ application: UIApplication, didFailToContinueUserActivityWithType userActivityType: String, error: Error) {
        print("[App] Did fail to continue user activity: ", userActivityType)
    }

    func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {

        print("[App] Application continue user activity...")

        if userActivity.activityType == NSUserActivityTypeBrowsingWeb {
            if let url = userActivity.webpageURL {
                if !present(url: url) { UIApplication.shared.open(url, options: [:]) }
            }
        }
        return true
    }

App is being opened but the methods are not called and I cannot navigate to appropriate screen inside my app.

Upvotes: 4

Views: 2712

Answers (3)

Dakata
Dakata

Reputation: 1355

For the SwiftUI 2.0 users, who don't have App or SceneDelegate. My example is about Firebase universal link, which should do something once it is opened. There is a very good method called onOpenURL which you can use.

 var body: some Scene {
    
    WindowGroup {
        ContentView(shouldPresentThankYouView: $shouldPresentThankYouView).onOpenURL { url in
            
            _ = DynamicLinks.dynamicLinks().handleUniversalLink(url) { (dynamicLink, error) in
                guard error == nil else{
                    print("Found an error! \(error!.localizedDescription)")
                    return
                }
                if let dynamicLink = dynamicLink {
                    shouldPresentThankYouView = true
                    self.handleIncomingDynamicLink(dynamicLink)
                }
            }
        }
      } 
     }

If the user has the app installed, once he click on the app, a Thank You View will appear. Hope it helps you when working it universal links more specifically with Firebase links.

Upvotes: 0

clopex
clopex

Reputation: 459

For me, only solution is to delete SceneDelegate and put code inside AppDelegate and it works, whenever the app is killed or in background. If you don use SwiftUI you can delete SceneDelegate

Upvotes: 0

Michał Ziobro
Michał Ziobro

Reputation: 11812

Ok I've found it you must do something like this

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
   
    if let userActivity = connectionOptions.userActivities.first {
      self.scene(scene, continue: userActivity)
    }
  }

Upvotes: 13

Related Questions