如何在处理通用链接之前等待 didFinishLaunchingWithOptions 完成?

shi*_*him 1 ios appdelegate swift ios-universal-links

AppDelegate在我的 Swift iOS 应用程序中,我在内部异步设置了初始视图控制器didFinishLaunchingWithOptions。现在我添加了一个通用链接,这样如果您转到手机上的相应 URL,它将自动打开应用程序中的正确页面(在本例中,它是一个密码重置 URL,如果正确,将打开密码重置表单在应用程序内)。

我正在处理application(_:continue:restorationHandler:)continueUserActivityAppDelegate.

如果应用程序已经在运行,则它可以工作,但否则链接处理会在我的应用程序完成设置初始视图控制器之前发生,并且didFinishLaunchingWithOptions返回时深层链接的视图控制器将被关闭。

在呈现视图控制器之前,如何确保应用程序已完成设置continueUserActivitydidFinishLaunching在设置视图控制器之前,我不能/不应该阻止返回,因此该方法在呈现初始视图控制器之前返回。

我知道我可以检查内部的用户活动字典,didFinishLaunchingWithOptionscontinueUserActivity仍然被调用(如果仅在应用程序运行时调用它会简单得多,就像didReceiveRemoteNotification工作原理一样)。是否有一个条件要检查此方法内部以将链接处理推迟到didFinishLaunching

一些简化的UIApplicationDelegate代码有助于解释:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    doSomeAsyncSetup(
        completion: {
            presentSomeViewController()
        }
    )
    return true
}

func application(_: UIApplication, continue userActivity: NSUserActivity, restorationHandler _: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
    if userActivity.activityType == NSUserActivityTypeBrowsingWeb,
        let url = userActivity.webpageURL,
        let components = NSURLComponents(url: url, resolvingAgainstBaseURL: true),
        let params = components.queryItems,
        components.path == pathThatIExpect
    {
            handleUniversalLink(params)
    }
    return true
}
Run Code Online (Sandbox Code Playgroud)

Scenes请注意,当应用程序选择加入但我的应用程序未使用它(https://developer.apple.com/documentation/xcode/supporting-universal-links-in-your-app)时,似乎略有不同。

Pau*_*w11 5

ADispatchGroup应该可以帮你处理这个事情。

private let dispatchGroup = DispatchGroup()

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    self.dispatchGroup.enter()
    doSomeAsyncSetup(
        completion: {
            presentSomeViewController()
            self.dispatchGroup.leave()
        }
    )
    return true
}

func application(_: UIApplication, continue userActivity: NSUserActivity, restorationHandler _: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
    if userActivity.activityType == NSUserActivityTypeBrowsingWeb,
        let url = userActivity.webpageURL,
        let components = NSURLComponents(url: url, resolvingAgainstBaseURL: true),
        let params = components.queryItems,
        components.path == pathThatIExpect
    {
            self.dispatchGroup.notify {
                handleUniversalLink(params)
            }
    }
    return true
}
Run Code Online (Sandbox Code Playgroud)

在启动应用程序的情况下,将输入调度组didFinishLaunching,并在呈现视图控制器后将其保留。一旦调度组为空,就会notify执行用户活动代码;所以只有在你的视图控制器出现之后。

如果您的应用程序已经启动,则调度组将为空,因为didFinishLaunching没有被调用,因此将notify立即执行