Swift使用UIApplication.shared.keyWindow添加自定义视图无效问题咨询
问题分析与解决方案
这个问题我之前在iOS 13+项目里也踩过坑!核心原因是苹果从iOS 13开始引入了UIScene场景架构,彻底改变了应用窗口的管理逻辑,导致UIApplication.shared.keyWindow不再是获取当前活跃显示窗口的可靠方式。
为什么keyWindow添加视图不显示?
在iOS 13之前,一个应用通常只有一个窗口,keyWindow能准确指向当前接收用户事件、正在显示的窗口。但iOS 13之后:
- 应用可以同时存在多个窗口(比如iPad的分屏多窗口、Mac Catalyst应用)
UIApplication.shared.keyWindow被标记为废弃属性,它可能返回第一个创建的窗口,或者直接返回nil,你添加的bigView其实被加到了一个非当前显示的窗口(甚至不存在的窗口)上,自然看不到。
正确的解决方法
方法1:从当前ViewController的视图获取所在窗口
这是最直接的方式,因为你的ViewController已经在当前显示的窗口上,通过它的view.window属性可以拿到正确的窗口:
// 在ViewController中 if let currentWindow = self.view.window { // 记得先设置bigView的布局,不然即使添加了也看不到 bigView.frame = currentWindow.bounds // 如果用AutoLayout,要关掉自动转换mask并添加约束 bigView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ bigView.topAnchor.constraint(equalTo: currentWindow.topAnchor), bigView.leadingAnchor.constraint(equalTo: currentWindow.leadingAnchor), bigView.trailingAnchor.constraint(equalTo: currentWindow.trailingAnchor), bigView.bottomAnchor.constraint(equalTo: currentWindow.bottomAnchor) ]) currentWindow.addSubview(bigView) }
方法2:通过场景获取当前活跃窗口
如果你需要在没有ViewController的上下文(比如工具类)中获取窗口,可以通过应用的场景会话来查找:
// 获取当前活跃的窗口场景 if let windowScene = UIApplication.shared.connectedScenes .filter({ $0.activationState == .foregroundActive }) .first as? UIWindowScene, // 找到场景中作为keyWindow的窗口(避免拿到弹窗等临时窗口) let currentWindow = windowScene.windows.first(where: { $0.isKeyWindow }) { currentWindow.addSubview(bigView) // 同样要设置布局... }
额外检查点
除了窗口获取的问题,还要确认:
bigView的backgroundColor是否设置了?如果是透明背景,即使添加了也可能看不到bigView的isHidden属性是否为false- 如果用AutoLayout,是否正确添加了约束,没有开启
translatesAutoresizingMaskIntoConstraints(这个属性默认为true,会导致约束不生效)
内容的提问来源于stack exchange,提问作者The Swift Apprentice
相关产品推荐
相关产品推荐

