前言
我们有时候会遇到需要显示加载框,统一封装的时候,有时候调用会给它一个 view 用作父视图,如果没有父视图,要考虑把它加载在什么上面。
例如获取当前显示的 UIViewController 还是使用 window。获取当前的 UIViewController 的话可能会遇到添加该加载框后,view 又添加了其他 view 覆盖住加载框。所以还是使用 window ,项目中使用 window 遇到添加 view 后未显示。解决笔记如下。
UIWindow的获取方式有四种
1. 某个 view 所在的 window:
如果是 UIViewController 的 View ,有时候 window 为 null ,原因是 view 没有完全加载完成或者在 ViewDidload 中才刚刚加载完,view 的 window 属性无法被获取)。
UIWindow *window = self.view.window;
2. keyWindow
可以添加 view 并显示出来的(有可能获取到是 nil)。
获取应用程序的主窗口,用来接收键盘以及非触摸类的消息事件的 UIWindow ,而且程序中每个时刻只能有一个 UIWindow 是 keyWindow 。
提示:如果某个 UIWindow 内部的文本框不能输入文字,可能是因为这个 UIWindow 不是 keyWindow 。
UIWindow *window = [UIApplication sharedApplication].keyWindow;
3. delegate
这个 window 添加的 view 很有可能被控制器的 view 覆盖而显示不了。
UIWindow *window = [[[UIApplication sharedApplication] delegate] window];
keyWindow 与 delegate 中的 window 其实是一样的,keyWindow 的存在的意义,其实就是为了说明当前的 window 接管了这个控制器的view而已,你可以在 keyWindow 上加载你自己的建立的 view 了。
4. windows
获取当前顶层的窗口。
UIWindow *window = [[[UIApplication sharedApplication] windows] lastObject];
keyWindow 即便获取到不是 nil,有时候也会有其它 window 覆盖在上面,导致添加上去的 view 不会显示。所以使用第该方式 windows 获取。
例如:在销售 APP 中遇到的 keyWindow 获取成功,但是上面还有一个 UITextEffectsWindow 覆盖了 keyWindow 添加的 加载框。
但是要注意,移除加载框的时候,因为 windows 中的数据是变化的,所以移除的时候要遍历 windows 中 window 查找,移除加载框。
代码如下:
@implementation MBProgressHUD (EHIProgressHUD)
#pragma mark - 显示加载框
+ (MBProgressHUD *)ehi_showLoadViewWithMessage:(NSString *)message {
return [self ehi_showLoadViewWithMessage:message toView:nil];
}
+ (MBProgressHUD *)ehi_showLoadViewWithMessage:(NSString *)message toView:(UIView *)view {
[self ehi_hideHUD];
if (view == nil) {
view = [[[UIApplication sharedApplication] windows] lastObject];
view.tag = EHITEMPVIEW_TAG;
}
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:view animated:YES];
hud.label.text = message;
return hud;
}
#pragma mark - 移除加载框
+ (void)ehi_hideHUD {
[self ehi_hideHUDForView:nil];
}
+ (void)ehi_hideHUDForView:(UIView *)view {
if (view == nil) {
for (UIWindow *window in [[UIApplication sharedApplication] windows]) {
view = [window viewWithTag:EHITEMPVIEW_TAG];
if (view) {
[self hideHUDForView:view animated:YES];
}
}
}
参考
iOS UIWindow:获取屏幕最上层的窗口(这篇文章有一点说的不对,keywindow不是随时获取的到的)
keyWindow与delegate中Window的区别
(说明了keywindow不是随时获取的到的)