iOS 13中未调用application(...continue userActivity...)方法

33

嗨,我正在使用UniversalLink制作iOS应用程序。

通用链接运行良好,但是回调方法(callback method)没有被调用。

我的AppDelegate.swift文件如下。

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
    }
}

该方法在iOS 12模拟器中调用。

因此,问题仅发生在iOS 13中。

仅在iOS 13中,此错误会在控制台中打印。

无法结束BackgroundTask:不存在标识符为1(0x1)的后台任务,或者它可能已经结束。在UIApplicationEndBackgroundTaskError()中断点以进行调试。

因此,这可能是问题的原因。

我真的很感激有人帮助。


4
我也有同样的问题。 - Emre Önder
2
这个问题有什么更新吗? - jfredsilva
1
有人找到了解决这个问题的方法吗? - Jan
@EmreÖnder 我找到了一个解决方案(请查看答案)。希望它能解决你的问题。 - Jan
@jfredsilva 我找到了一个解决方案(请查看答案)。希望它能解决你的问题。 - Jan
4个回答

46

我曾经遇到过与SceneDelegate和通用链接相关的类似问题,其中我无法在应用程序刚启动时获取NSUserActivity(在这种情况下是iOS 13中的后台NFC读取)。

如@Jan所述的答案中提到的,继续使用userActivity现在在SceneDelegate中。

如果应用程序正在运行或处于后台即关闭状态,则通用链接将触发scene(_:continue:)委托。

如果应用程序不在后台,则通用链接不会从scene(_:continue:)委托中启动。相反,NSUserActivity将从scene(_:willConnectTo:options:)中可用。

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

3
值得注意的是,在iOS 13.4.1中,由于某种原因,“scene.userActivity”在此处为nil。但是你所说的方法非常有效:“let userActivity = connectionOptions.userActivities.first”。 - jangelsb

41

我的情况是,在 Xcode 11 上启动了一个全新的项目,该项目使用 SceneDelegateAppDelegate

看起来像万能链接(以及可能是其他几个API),会在 SceneDelegate 上使用此回调函数:

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

不要在AppDelegate上使用此回调函数:

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

一旦我在SceneDelegate上实现了这个方法,一切又恢复正常了。我没有尝试过,但我假设如果你的目标是iOS 12及以下版本,你可能需要同时实现两种方法。

希望这可以帮助你


1
它也不起作用。苹果在iOS 13中确认了这个问题。当然,他们不会修复它。 - Dmitry
1
相关问题链接:https://dev59.com/AlMH5IYBdhLWcg3wzi96 - Dmitry
3
太棒了,我将 func scene(_ scene: UIScene, continue userActivity: NSUserActivity) { } 放到 SceneDelegate 中,现在它完全正常工作了。@Jan,有没有办法避免在 AppDelegate 和 SceneDelegate 中重复编写代码的情况呢?谢谢。 - Jigar
1
@Jigar,我认为你现在甚至不需要在AppDelegate中编写代码。 - Jan
1
@Jan 我移除了 SceneDelegate,之后它就正常工作了。 - Jigar

7

对于 SwiftUI 应用程序,现在有另一种方法来处理通用链接或任何 URL,假设用户已经安装了该应用程序。

您可以在主 App Struct 中的视图上简单地使用 .onOpenURL() 修饰符。

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

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

并实现您自己的函数,例如:

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

}

您可以根据自己的需求处理通用链接。

对于延迟深度链接,即处理安装前点击的链接,您仍需要实现SceneDelegate方法。


2
就是这样!甚至不知道这个存在。苹果添加了许多新的修饰符,以慢慢替换AppDelegate和SceneDelegate。这篇文章是我第一次接触到这些修饰符有多么强大和易用的:https://peterfriese.dev/posts/ultimate-guide-to-swiftui2-application-lifecycle/#handling-deep-links - Throvn
感谢您在23上提供的信息。这是我今天看到的第一个参考,正是我需要让我的工作起来的东西。太疯狂了。 - mylogon
我花了几天时间努力解决它。谢谢。 - Mahdi Moqadasi
这是一整天的搜索/测试的结束。我找不到关于这个和SceneDelegatecontinue方法之间关系的任何文档,但在我的情况下,SceneDelegate的所有其他方法都能触发,只有continue方法不能。尽管它应该起作用,但这让我克服了困难。非常感谢。 - undefined

1
将此函数添加到您的SceneDelegate类中:
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) { if let url = userActivity.webpageURL { print(url) }}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接