iOS开发笔记:UIWindow获取

前言

我们有时候会遇到需要显示加载框,统一封装的时候,有时候调用会给它一个 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不是随时获取的到的)

  • iOS 关于UIWindow 的认识

  • iOS UIWindow 及悬浮球

  • iOS开发UI篇—UIWindow简单介绍

你可能感兴趣的:(iOS开发笔记:UIWindow获取)