Swift iOS如何在didFinishLaunchingWithOptions完成后处理Universal Link
解决方案
你可以通过增加初始化状态标记 + 待处理链路缓存的方式实现需求,无需阻塞didFinishLaunching返回,逻辑如下:
步骤1:在AppDelegate增加两个私有属性
用来记录应用初始化状态,以及暂存未及时处理的Universal Link参数:
// 标记应用初始视图控制器设置是否完成 private var isAppInitialSetupCompleted = false // 暂存待处理的Universal Link参数,可根据需求扩展为枚举支持多类型深度链接 private var pendingUniversalLinkParams: [URLQueryItem]?
步骤2:修改初始化完成回调
在异步设置初始视图控制器的完成回调中,更新状态标记,同时检查是否有待处理的链路需要执行:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { doSomeAsyncSetup( completion: { [weak self] in self?.presentSomeViewController() // 标记初始化完成 self?.isAppInitialSetupCompleted = true // 检查是否有缓存的待处理Universal Link guard let params = self?.pendingUniversalLinkParams else { return } self?.handleUniversalLink(params) // 处理完成后清空缓存,避免重复触发 self?.pendingUniversalLinkParams = nil } ) return true }
步骤3:修改continueUserActivity的处理逻辑
收到Universal Link时先判断当前初始化状态,已完成就直接处理,未完成就先缓存参数等待后续执行:
func application(_: UIApplication, continue userActivity: NSUserActivity, restorationHandler _: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool { guard userActivity.activityType == NSUserActivityTypeBrowsingWeb, let url = userActivity.webpageURL, let components = NSURLComponents(url: url, resolvingAgainstBaseURL: true), let params = components.queryItems, components.path == pathThatIExpect else { return false } if isAppInitialSetupCompleted { handleUniversalLink(params) } else { // 初始化未完成,先缓存参数 pendingUniversalLinkParams = params } return true }
额外优化建议
- 如果应用后续需要支持多种类型的深度链接,可以把缓存变量的类型改为自定义枚举,存储链路类型和对应参数,扩展性更强
- 可增加超时清理逻辑,比如缓存超过10秒未被消费就自动清空,避免极端场景下初始化失败导致缓存长期留存引发异常
handleUniversalLink方法内部需要先获取当前应用的顶层可视控制器,再执行跳转操作,避免出现找不到presentingViewController的崩溃问题
内容的提问来源于stack exchange,提问作者shim
相关产品推荐
相关产品推荐

