kazuwombat
kazuwombat

Reputation: 1653

application(...continue userActivity...) method not called in ios 13

Hi I'm making ios app using UniversalLink.

Universal Link works fine, but callback method is not called.

My AppDelegate.swift is below.

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        return true
    }


    func application(_ application: UIApplication,
                     willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        return true
    }

    // this method not called!!
    func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
        print("called")
        return true
    }
}

The method is called in iOS 12 Simulator.

So, the problem is occured only in iOS 13.

Only in iOS13 this error is printed in console.

Can't end BackgroundTask: no background task exists with identifier 1 (0x1), or it may have already been ended. Break in UIApplicationEndBackgroundTaskError() to debug.

So, this may be cause of the problem.

I'd really appreciate someone help

Upvotes: 35

Views: 15341

Answers (5)

Till
Till

Reputation: 1128

iOS 14.0 added onContinueUserActivity(_:perform:). See this answer.

Upvotes: 0

Hafiz Anser
Hafiz Anser

Reputation: 581

Add this fucntion in your SceneDelegate class

func scene(_ scene: UIScene, continue userActivity: NSUserActivity) { if let url = userActivity.webpageURL { print(url) }}

Upvotes: 2

Seamus
Seamus

Reputation: 1257

For SwiftUI apps there is now another approach to handle a universal link or any url, assuming the user already has the app in installed.

you can simply use the .onOpenURL() modifier on the view in your main App Struct.

struct MySwiftUIApp: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate

    var body: some Scene {
        WindowGroup {
            MainContentView()
                .onOpenURL { url in
                    handleURL(url)
                }
        }
    }
}

and Implement your own function such as:

@discardableResult func handleURL(_ url: URL) -> Bool {

}

to handle universal links how you wish.

For Differed deeplinking, i.e. to handle a link clicked before install you will still need to implement the SceneDelegate method.

Upvotes: 11

Rex
Rex

Reputation: 587

I had a similar issue with SceneDelegate and universal links where I could not get to NSUserActivity when the app was just launched (in this case Background NFC reading in ios 13).

As mentioned in the answer by @Jan, continue userActivity is now in the SceneDelegate.

If the app is running or in the background ie. closed, a universal link will fire the scene(_:continue:) delegate.

If the app is not in the background, a universal link won't fire up from the scene(_:continue:) delegate. Instead, the NSUserActivity will be available from scene(_:willConnectTo:options:). eg.

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    if let userActivity = connectionOptions.userActivities.first {
        debugPrint("got user activity")
    }
}

Upvotes: 47

Jan
Jan

Reputation: 2522

In my case, I started a brand new project on Xcode 11 which uses SceneDelegate as well as AppDelegate

Looks like UniversalLinks (and probably several other APIs) use this callback on the SceneDelegate:

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

Instead of this callback on the AppDelegate:

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

Once I implemented the one on SceneDelegate everything started working as expected again. I haven't tried it, but I'm assuming that if you are targeting iOS 12 and below, you might need to implement both methods.

Hope this helps

Upvotes: 41

Related Questions