自定义弹窗——keyWindow和delegate.window

本文探讨了在自定义弹窗时遇到的一个bug,即视图在系统弹窗出现后可能消失。问题的关键在于理解keyWindow和delegate.window之间的区别。当系统弹窗出现时,keyWindow会改变,而delegate.window保持不变。为了解决这个问题,作者建议将自定义视图添加到delegate.window上,而不是keyWindow,以确保视图在系统弹窗出现后仍然可见。文章提供了一个相关代码的GitHub链接以及参考资料,帮助读者理解并避免此类问题。

之前的自定义弹窗总是添加到keyWindow上,一直屡试不爽。最后遇到了一个bug。
在这里插入图片描述
bug描述:
1、在系统弹窗出现【之后】,添加到keyWindow上的视图【会】随着弹窗的消失而消失。
2、在系统弹窗出现【之前】,添加到keyWindow上的视图就【不会】随着弹窗的消失而消失。
通过上面的描述,可以看到我们可以通过2的方式来解决这个问题。但是怎样确保顺序呢?显然是不靠谱的方案。

最终解决方案:在系统弹窗出现【之前】,添加到keyWindow上的视图就【不会】随着弹窗的消失而消失。

我的demo请参考:https://github.com/wokenshin/Laboratory
全局搜索:KeyWindowVC 即可找到相关代码

那么为什么要将视图放在delegate.window上,而不是keyWindow上呢?
请看下图
在这里插入图片描述
如上图所述:默认情况下keyWindow和delegate.window是同一个对象(通过打印的内存地址可知)。但是当有系统弹窗出现的时候,keyWindow就变成了另外一个对象。
delegate.window 程序启动时设置的window对象
keyWindow 这个属性保存了[windows]数组中的[UIWindow]对象,该对象最近被发送了[makeKeyAndVisible]消息

另外这里的问题在之前已经有朋友遇到过了:
//参考

### UIWindow 获取方式的区别分析 在 iOS 开发中,获取 `UIWindow` 实例通常会使用两种方法:`[[UIApplication sharedApplication] keyWindow]` `[[UIApplication sharedApplication].delegate window]`。这两种方式虽然都能获取到窗口实例,但它们的用途行为存在显著差异。 #### 1. `keyWindow` 的作用与特点 `keyWindow` 是一个系统管理的属性,表示当前接收键盘事件的窗口。这个窗口通常是用户正在交互的窗口。例如: ```objective-c UIWindow *currentKeyWindow = [[UIApplication sharedApplication] keyWindow]; ``` - **动态性**:`keyWindow` 是动态变化的,当有新的窗口(如弹窗、系统通知等)覆盖在主窗口上时,`keyWindow` 会指向这个新窗口。 - **多窗口支持**:在 iPadOS 支持分屏功能的情况下,可能会同时存在多个窗口,此时 `keyWindow` 表示当前聚焦的窗口。 - **潜在为 nil**:在某些情况下,比如应用刚启动或窗口尚未完全初始化时,`keyWindow` 可能为 `nil` [^1]。 #### 2. `delegate.window` 的作用与特点 `delegate.window` 是由开发者手动创建并赋值的窗口,通常在 `AppDelegate` 中进行初始化: ```objective-c - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // 设置 rootViewController 并调用 makeKeyAndVisible [self.window makeKeyAndVisible]; return YES; } ``` - **静态性**:`delegate.window` 是开发者显式创建的窗口,通常在整个应用程序生命周期内保持不变。 - **可靠性**:由于是开发者直接管理的窗口,因此它的值通常不会为 `nil`,除非开发者未正确初始化它。 - **与 `keyWindow` 的关系**:在正常情况下,`delegate.window` 通常就是 `keyWindow`,但在特定场景下(如显示自定义弹窗时),两者可能不一致 [^3]。 #### 3. 两者的区别总结 | 特性 | `keyWindow` | `delegate.window` | |---------------------|--------------------------------------|--------------------------------------| | 来源 | 系统自动管理 | 开发者手动创建并赋值 | | 是否动态变化 | 是 | 否 | | 是否可能为 `nil` | 是 | 否(假设已正确初始化) | | 是否始终指向主窗口 | 否 | 是 | | 多窗口环境下的表现 | 指向当前焦点窗口 | 始终指向开发者设定的主窗口 | #### 4. 使用建议 - **需要获取当前交互窗口时**:应使用 `keyWindow`,特别是在需要响应用户输入或显示弹窗时。 - **需要操作主窗口时**:应使用 `delegate.window`,尤其是当需要确保操作的是应用程序的主窗口时。 - **避免依赖 `keyWindow` 为非 `nil`**:在某些特殊场景下(如应用启动初期),`keyWindow` 可能为 `nil`,因此在使用前最好进行判空处理。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值