iOS-Swift中使用Universal Link实现Deep Linking的跳转问题处理
解决方案
核心思路是暂存深度链接参数,根据用户登录状态和当前页面栈决定立即处理还是等待登录完成后触发跳转,同时覆盖前台/后台唤醒场景。
1. 重构UniversalLinkManager
替换原有的UserDefaults存储方式,改为单例内部暂存参数,并增加状态检查和跳转逻辑:
import Foundation import UIKit class UniversalLinkManager { static let shared = UniversalLinkManager() // 暂存待处理的深度链接参数 private var pendingLinkParams: [String: String]? private init() {} func handleUniversalLink(url: URL) { var queryParams: [String: String] = [:] if let components = URLComponents(url: url, resolvingAgainstBaseURL: true), let params = components.queryItems { params.forEach { if let value = $0.value { queryParams[$0.name] = value } } } // 判断当前是否已登录并处于Tabbar页面 if isUserLoggedInAndInTabbar() { // 直接跳转目标页面 navigateToTargetVC(with: queryParams) } else { // 暂存参数,等待登录完成后处理 pendingLinkParams = queryParams } } // 检查当前登录状态和页面栈 private func isUserLoggedInAndInTabbar() -> Bool { guard let window = UIApplication.shared.windows.first else { return false } // 替换成你项目中实际的登录状态判断逻辑 let isLoggedIn = UserDefaults.standard.bool(forKey: "isLoggedIn") return isLoggedIn && window.rootViewController is UITabBarController } // 根据参数跳转目标ViewController func navigateToTargetVC(with params: [String: String]) { guard let tabbarVC = UIApplication.shared.windows.first?.rootViewController as? UITabBarController else { return } // 示例:根据参数跳转到Tabbar下的目标页面(替换成你的实际页面逻辑) if let targetVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "TargetViewController") as? TargetViewController { targetVC.serviceInfo = params["serviceInfo"] // 假设Tabbar的当前选中项是导航控制器,直接push if let navVC = tabbarVC.selectedViewController as? UINavigationController { navVC.pushViewController(targetVC, animated: true) } else { // 如果选中项不是导航控制器,可改为present tabbarVC.selectedViewController?.present(targetVC, animated: true) } } } // 登录完成后调用,检查并处理暂存的链接 func processPendingLinkAfterLogin() { guard let params = pendingLinkParams else { return } navigateToTargetVC(with: params) pendingLinkParams = nil // 处理后清空暂存 } }
2. 保持AppDelegate回调逻辑
原有的continue userActivity回调无需大幅修改,直接调用重构后的Manager:
func application(_: UIApplication, continue userActivity: NSUserActivity, restorationHandler _: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool { guard userActivity.activityType == NSUserActivityTypeBrowsingWeb, let url = userActivity.webpageURL else { return false } UniversalLinkManager.shared.handleUniversalLink(url: url) return true }
3. 登录完成后触发跳转
在登录成功的代码逻辑中,切换到TabbarViewController后,立即调用Manager的处理方法:
// 登录成功后设置登录状态 UserDefaults.standard.set(true, forKey: "isLoggedIn") // 切换根视图到Tabbar let tabbarVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "TabbarViewController") as! UITabBarController UIApplication.shared.windows.first?.rootViewController = tabbarVC // 检查是否有暂存的深度链接需要处理 UniversalLinkManager.shared.processPendingLinkAfterLogin()
4. 处理Splash页面的场景
如果Splash页面需要自动判断登录状态并跳转:
class SplashViewController: UIViewController { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) let isLoggedIn = UserDefaults.standard.bool(forKey: "isLoggedIn") if isLoggedIn { // 直接进入Tabbar let tabbarVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "TabbarViewController") as! UITabBarController UIApplication.shared.windows.first?.rootViewController = tabbarVC // 检查暂存链接 UniversalLinkManager.shared.processPendingLinkAfterLogin() } else { // 进入登录页面 let loginVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "LoginViewController") as! LoginViewController present(loginVC, animated: true) } } }
关键说明
- 前台场景:若用户已在Tabbar页面,点击深度链接直接跳转;若在Login/Splash页面,暂存参数,等登录完成后自动触发。
- 后台场景:唤醒APP后,Manager会自动判断当前状态,已登录则直接跳转,未登录则暂存,等后续登录流程完成后处理。
- 避免了UserDefaults监听延迟、通知时机不对的问题,通过主动检查的方式保证跳转时机准确。
内容的提问来源于stack exchange,提问作者Irtaza Hussain
相关产品推荐
相关产品推荐

