Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

ios

swift

ios13

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

like image 573
kazuwombat Avatar asked Oct 03 '19 07:10

kazuwombat


3 Answers

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")
    }
}
like image 167
Rex Avatar answered Nov 08 '22 12:11

Rex


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

like image 39
Jan Avatar answered Nov 08 '22 10:11

Jan


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.

like image 1
Seamus Avatar answered Nov 08 '22 11:11

Seamus