You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何canActivateForTargetContentIdentifierPredicate为false时场景仍被激活?

问题描述

以下代码来自苹果WWDC 2019 Session 212:《iPad多窗口介绍》

apple WWDC 2019 session 212: Introducing Multiple Windows on iPad

let mainSceneTargetContentIdentifier = "com.apple.gallery.mainIdentifier"

var window: UIWindow?

// MARK: - UIWindowSceneDelegate

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    print("willConnectTo") //3
    
    if let userActivity = connectionOptions.userActivities.first ?? session.stateRestorationActivity {
        if !configure(window: window, with: userActivity) {
            Swift.debugPrint("Failed to restore from \(userActivity)")
        }
    }
    // The 'window' property will automatically be loaded with the storyboard's initial view controller.
    
    // Set the activation predicates, which operate on the 'targetContentIdentifier'.
    let conditions = scene.activationConditions
    let prefsPredicate = NSPredicate(format: "self == %@", mainSceneTargetContentIdentifier)
    // The main predicate, which expresses to the system what kind of content the scene can display.
    conditions.canActivateForTargetContentIdentifierPredicate = prefsPredicate
    // The secondary predicate, which expresses to the system that this scene is especially interested in a particular kind of content.
    conditions.prefersToActivateForTargetContentIdentifierPredicate = prefsPredicate
}

当前targetContentIdentifier的值为com.apple.gallery.openDetail,而mainSceneTargetContentIdentifier的值为com.apple.gallery.mainIdentifier,因此NSPredicate(format: "self == %@", mainSceneTargetContentIdentifier)的对比结果应该是false,但场景仍被激活。甚至直接初始化NSPredicate(value:false)赋值给场景条件,场景依然会被激活。根据文档描述,只有当谓词返回true时场景才应被激活,请问这是什么原因?


问题解答

这是因为场景激活的规则并非仅由canActivateForTargetContentIdentifierPredicate决定,核心原因如下:

  1. 初始场景的强制激活逻辑
    应用启动创建第一个场景时,系统会直接触发激活流程,不会严格校验canActivateForTargetContentIdentifierPredicate。这个谓词的作用范围是后续的场景创建/激活请求(比如通过UIApplication.requestSceneSessionActivation触发的场景激活、系统自动的场景恢复),而非应用首次启动的初始场景。

  2. 状态恢复的优先级高于谓词校验
    如果场景是通过session.stateRestorationActivity触发的状态恢复流程,系统会优先完成状态恢复,此时canActivateForTargetContentIdentifierPredicate的校验会被跳过。你代码中已经处理了状态恢复逻辑,这是场景被激活的直接触发点。

  3. 谓词生效的时机滞后
    在willConnectTo方法中设置谓词时,场景已经处于激活流程中,这个设置无法影响当前的激活行为,仅会对后续的场景激活请求生效。

要验证谓词的实际作用,可以尝试:

  • 先启动应用创建主场景,再通过携带com.apple.gallery.openDetail的NSUserActivity请求激活新场景,此时系统会因谓词不匹配而拒绝创建/激活该场景。
  • 在场景完全激活后(比如sceneDidBecomeActive方法中)设置谓词,再测试后续的激活请求。

内容的提问来源于stack exchange,提问作者Alyafai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 12:43:24