iOS检测启动源的sourceApplication是否废弃?有哪些替代方案及SceneDelegate适配问题
外部App唤起检测与页面跳转的核心问题排查
为什么你的现有代码无法正常运行
你遇到的所有问题本质都是iOS 13引入Scene架构后的职责拆分调整,和字段废弃没有直接关系:
- 从iOS 13开始,所有和应用场景、外部App唤起、文件打开相关的参数传递,全部从AppDelegate的回调体系迁移到了SceneDelegate的回调体系。你在AppDelegate的
didFinishLaunchingWithOptions里读取launchOptions[.sourceApplication]时,系统根本不会把外部唤起的参数塞给这个字典,所以这个值永远是nil,自然只会走else分支打印"source app not identified"。 - 关于
sourceApplication字段的误区澄清:这个字段没有被全局废弃。你看到的“2019年被废弃”的说法,指的是老的application:openURL:options:这类AppDelegate层面的回调方法,而非sourceApplication字段本身。目前在Scene架构下,这个字段依然保留在UIScene.ConnectionOptions和UIOpenURLContext对象中,苹果官方文档的描述是准确的。
为什么页面切换只能在SceneDelegate生效
在Scene架构下,UIWindow不再是App全局持有的单例对象,而是每个独立的UIScene实例专属的展示载体。你在AppDelegate里哪怕写了切换根控制器的代码,操作的也是一个没有和当前屏幕绑定的空window,自然不会有任何实际效果。这不是近期的临时API调整,是Xcode 11之后所有新工程默认开启Scene支持的标准架构逻辑——从系统层面就把window的控制权下放给了SceneDelegate。
适配你PDF接收需求的正确实现方案
按照以下步骤调整代码即可:
- 冷启动场景(App完全退出时被外部App唤起):在SceneDelegate的
scene(_:willConnectTo:options:)方法中,从connectionOptions读取唤起来源和传入的PDF参数,再初始化根控制器。示例代码:// 定义全局变量存储待处理的PDF路径 var pendingPDFURL: URL? var startVC: String = "home" func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { // 读取外部唤起来源 if let sourceApp = connectionOptions.sourceApplication { print("检测到来自\(sourceApp)的外部唤起") // 读取传入的PDF文件链接 if let userActivity = connectionOptions.userActivities.first, userActivity.activityType == NSUserActivityTypeBrowsingWeb { pendingPDFURL = userActivity.referrerURL startVC = "addFile" } } // 初始化Storyboard、切换根控制器的逻辑和你原有实现保持一致 guard let windowScene = (scene as? UIWindowScene) else { return } let storyboard = UIStoryboard(name: "Main", bundle: nil) let targetVC = storyboard.instantiateViewController(withIdentifier: startVC) window?.rootViewController = targetVC window?.makeKeyAndVisible() } - 热启动场景(App在后台挂起时被外部App唤起):实现SceneDelegate的
scene(_:openURLContexts:)回调,在这个方法中拿到传入的PDF链接,直接在当前已展示的页面栈上跳转。示例代码:func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) { guard let fileContext = URLContexts.first else { return } let fileURL = fileContext.url // 直接在当前根控制器上展示接收PDF的页面 guard let rootVC = window?.rootViewController else { return } let addFileVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "addFile") as! addFileViewController addFileVC.receivedPDFURL = fileURL rootVC.present(addFileVC, animated: true) } - 可以直接删掉AppDelegate里读取sourceApplication的那段逻辑。如果你的应用需要兼容iOS 12及以下的旧系统版本,才需要在AppDelegate的启动回调里保留老的参数读取逻辑做版本兜底,否则这段代码在iOS13+的环境下不会有任何实际作用。
内容的提问来源于stack exchange,提问作者Markv07
相关产品推荐
相关产品推荐

