iPadOS 16 Stage Manager重叠窗口场景如何检测最上层窗口
iPadOS 16 重叠窗口/台前调度(Stage Manager)环境下检测应用最上层窗口实现方案
核心实现逻辑
iPadOS 16 引入台前调度后,传统单窗口模式下的窗口检测接口已经失效,需要基于UIWindowScene的激活状态做判断:同一时间只有处于foregroundActive状态的场景是用户当前正在交互的场景,再从该场景下筛选出层级最高的可见窗口即为当前最上层窗口。
可直接使用以下Swift代码实现:
func fetchTopMostWindow() -> UIWindow? { // 过滤所有已连接场景,仅保留前台激活状态的UIWindowScene let validScenes = UIApplication.shared.connectedScenes .filter { $0.activationState == .foregroundActive } .compactMap { $0 as? UIWindowScene } guard let activeScene = validScenes.first else { return nil } // 过滤隐藏、透明窗口,按窗口层级从高到低排序取首个 return activeScene.windows .filter { !$0.isHidden && $0.alpha > 0.01 } .sorted(by: { $0.windowLevel.rawValue > $1.windowLevel.rawValue }) .first }
注意事项
- 废弃的
UIApplication.shared.windows、旧版keyWindow属性不要用,这类接口在多窗口叠放场景下会随机返回非激活场景的窗口,检测结果完全不可靠 - 受系统沙盒限制,该方法只能检测当前应用内的最上层窗口,无法获取其他应用的窗口信息
- 系统弹出的权限弹窗、系统级浮层属于系统进程的窗口,不在当前应用的窗口列表内,不会被该方法捕获,属于正常现象
- 不需要做定时轮询检测,可以通过注册
UIWindowScene.didActivateNotification、UIWindow.didBecomeKeyNotification通知,在场景激活、窗口焦点变化时触发检测逻辑即可 - 如果应用采用SwiftUI生命周期,可以搭配环境值
scenePhase监听状态变化,当scenePhase为.active时再调用上述方法检测,结果准确率更高 - 被台前调度收起到叠层后方、未处于激活状态的应用窗口,其场景状态为
foregroundInactive,会被上述逻辑自动过滤,不会出现误判
内容的提问来源于stack exchange,提问作者Kuba
相关产品推荐
相关产品推荐

