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

Mac Catalyst技术问询:是否可将指定场景设置为激活状态?

解决Mac Catalyst多前台场景的激活问题

当然可行!你遇到的重复创建场景的问题,是因为调用requestSceneSessionActivation时没有指定已存在的目标场景会话,系统默认会创建新的场景副本。下面是具体的实现思路和代码示例:

核心思路

  1. 定位已存在的场景会话:遍历应用的所有打开场景会话(openSessions),通过自定义标识找到目标场景的UISceneSession。
  2. 判断场景状态:确认目标会话处于前台状态(foregroundActive或foregroundInactive,后者就是可见但非激活的状态)。
  3. 激活已有会话:调用requestSceneSessionActivation时传入找到的会话,而不是传nil,系统就会将该场景切换为激活状态(最前端)。

代码实现示例

1. 为场景会话添加唯一标识(创建场景时)

首先要确保每个场景在创建时都有唯一的标识,方便后续查找。在AppDelegate或SceneDelegate的场景配置方法中添加:

func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
    let config = UISceneConfiguration(name: "YourSceneConfigName", sessionRole: connectingSceneSession.role)
    // 这里用自定义ID标记场景,比如根据业务需求设置不同的标识
    connectingSceneSession.userInfo["targetSceneID"] = "product-detail-scene"
    return config
}

2. 激活已有前台场景的方法

实现一个工具方法,用来查找并激活目标场景:

func activateTargetScene(with sceneID: String) {
    // 遍历所有已打开的场景会话
    guard let targetSession = UIApplication.shared.openSessions.first(where: { session in
        // 匹配自定义标识,同时确保场景处于前台状态(非后台)
        guard let sessionSceneID = session.userInfo?["targetSceneID"] as? String else {
            return false
        }
        return sessionSceneID == sceneID && session.state != .background
    }) else {
        // 如果目标场景不存在,再执行创建新场景的逻辑
        createNewScene(with: sceneID)
        return
    }
    
    // 创建激活选项,可指定发起激活的场景(可选)
    let activationOptions = UIScene.ActivationRequestOptions()
    activationOptions.requestingScene = UIApplication.shared.connectedScenes.first as? UIWindowScene
    
    // 请求激活已存在的场景会话
    UIApplication.shared.requestSceneSessionActivation(
        targetSession,
        userActivity: nil,
        options: activationOptions
    ) { error in
        if let error = error {
            print("激活场景失败:\(error.localizedDescription)")
        }
    }
}

// 创建新场景的辅助方法(原有的创建逻辑)
private func createNewScene(with sceneID: String) {
    let config = UISceneConfiguration(name: "YourSceneConfigName", sessionRole: .windowApplication)
    // 给新会话设置标识
    let newSession = UISceneSession(configuration: config)
    newSession.userInfo["targetSceneID"] = sceneID
    
    UIApplication.shared.requestSceneSessionActivation(
        newSession,
        userActivity: nil,
        options: nil
    ) { error in
        if let error = error {
            print("创建新场景失败:\(error.localizedDescription)")
        }
    }
}

关键说明

  • 场景状态区分:Mac Catalyst中,UISceneSession.state的.foregroundInactive就是你说的“可见但非最前端”的状态,调用激活方法后会切换为.foregroundActive(最前端激活状态)。
  • 避免重复创建:只要传入已存在的UISceneSession实例,系统就不会创建新的场景副本,而是直接激活现有场景。
  • 多窗口配置:确保你的应用已经开启多窗口支持——在Xcode项目设置的“Deployment Info”中勾选“Supports multiple windows”,或者在Info.plist的UIApplicationSceneManifest下设置Enable Multiple Windows为YES。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 16:22:31