UIWindow

  1. 父类是UIView,它是一个特别的UIView
  • 每个App至少有一个UIWindow,是第一个创建的视图控件。

UIApplication中的窗口及其层级

  1. 设置窗口的层级,层级谁大就显示在最外面
窗口的层级 代表窗口 层级
UIWindowLevelNormal 默认窗口的层级(含主窗口)
UIWindowLevelStatusBar 键盘;状态栏(无法通过application.windows打印显示,原因是它没有交给application管理)
UIWindowLevelAlert UIActionSheet,UIAlearView
// 窗口的层级本质是枚举值(数字),数字越大,层级越高
self.window1.windowLevel = UIWindowLevelAlert
self.window2.windowLevel = UIWindowLevelAlert + 1 //显示在最外层

UIWindow创建

  1. 创建时间:程序启动完毕的时候才创建
  2. 创建方式:
    1. 系统自动创建窗口详见UIStoryboard中系统加载指定storyboard的流程
      通过storyboard加载程序,窗口都交给系统创建及管理,不需要我们管理
    2. 代码创建(常用):
      步骤:
      1. 创建窗口
      2. 加载根控制器
      3. 设置窗口的根控制器,显示窗口
      // 在开发中通常在程序启动完成的时候手动创建窗口
      - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
      
      // 1.创建窗口
      // self -> AppDelegate
      self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
      
      // 1.1设置颜色(可选)
      // self.window.backgroundColor = [UIColor yellowColor];
      
      // 2.创建根控制器,在设置窗口的根控制器
      UIViewController *vc = [[UIViewController alloc] init];
      self.window.rootViewController = vc;
      
      // 3.显示窗口
      [self.window makeKeyAndVisible];
      
      return YES;
      }
      

UIWindow的常用方法

// 让当前UIWindow变成keyWindow(主窗口)
[window makeKeyWindow];

// 让当前UIWindow变成keyWindow,并显示出来(hidden属性为NO)
// 注意,若再创建一个window,调用makeKeyAndVisible方法,并不会使之前的window隐藏
[window makeKeyAndVisible];

// 在本应用中打开的UIWindow列表
// 这样就可以接触应用中的任何一个UIView对象(平时输入文字弹出的键盘,就处在一个新的UIWindow中)
NSLog(@"%@",[UIApplication sharedApplication].windows);

// 用来接收键盘以及非触摸类的消息事件的UIWindow
// 程序中每个时刻只能有一个UIWindow是keyWindow
[UIApplication sharedApplication].keyWindow

//获得某个UIView所在的UIWindow,可用于判断是否已加入到控件中,避免重复添加
if (view.window) return;

窗口与根控制器

  1. 设置窗口的根控制器,底层会自动把根控制器的view添加到窗口上,并且让控制器的view有旋转功能
  • 为什么要用根控制器开发,没有跟控制器一样能显示界面。
    原因:
    1. 开发中会存在很多界面,为了管理方便,通常一个界面交给一个控制器管理,逻辑清晰
    2. 控制器有专门的view生命周期方法,用于处理UIView遇到的事件
    3. 若直接通过addSubView将控制器的view添加到窗口中,控制器会被释放,控制器就不能处理事件,另外控制器的view不会自动旋转。

  • 每个控制器的view都是懒加载的,所以不要在窗口中设置根控制器view的属性;而应该在根控制器中设置

  • 切换根控制器的常见用处:
    当新特性界面展示完成,切换到主界面,这时只需要切换根控制器,新特性界面就会自动销毁,显示主界面。

  • IOS9之后必须在程序启动完毕那一刻显示出来的窗口必须要设置根控制器;IOS9之前不尽然

UIWindow的内存管理与显示注意细节

  1. 一定要强引用窗口
    1. 必须设置AppDelegate.window = window,这样会被AppDelegate用强指针指向,不会被释放;
    2. 如果不设置AppDelegate.window,直接让新创建的window成为主窗口并显示,结果是黑屏;通过自定义窗口在dealloc中打印语句,检测结果是:窗口销毁了

  2. 必须有尺寸
    建议与屏幕同宽同高

  3. 成为主窗口,或设置hidden属性为NO

    [window makeKeyAndVisible];
    // window.hidden = NO
    

4. 经过前3步,窗口已经在应用程序显示,但所有UIView默认颜色是clearColor,只有设置其他颜色才能被我们发现
        1. 若没有设置颜色,也没有其他控件显示,最终显示的是屏幕(屏幕颜色是黑色,所以肉眼所见就是黑色)
        2. 应用程序显示从内到外是:屏幕->主窗口->根控制的View->子控件(或子控件的子控件...)。最终显示的是最外层控件

5. 存在多个窗口时,预期的窗口没有出现,检查窗口的层级
,判断是否被其他窗口遮挡


### 窗口->主窗口时间
* 应用程序自动加载,新建的窗口成为主窗口时间:是在根控制器的View完成显示时,测试时间及结果如下:
    ```objc
    // 测试时间1:控件加载中
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        NSLog(@"keywindow%@---%@",[UIApplication sharedApplication].keyWindow,[UIApplication sharedApplication].windows);
    }

    // 测试时间2:控件即将显示
    - (void)viewWillAppear:(BOOL)animated
    {
        [super viewWillAppear:animated];

        NSLog(@"keywindow%@---%@",[UIApplication sharedApplication].keyWindow,[UIApplication sharedApplication].windows);
    }

    // 测试时间3:控件已经显示
    - (void)viewDidAppear:(BOOL)animated
    {
        [super viewDidAppear:animated];
        NSLog(@"keywindow%@---%@",[UIApplication sharedApplication].keyWindow,[UIApplication sharedApplication].windows);
    }
    ```
    ```objc
    // viewDidLoad打印结果
    keywindow(null)---
    (
        "; layer = >"
    )

    // viewWillAppear打印结果
    keywindow(null)---
    (
        "; layer = >"
    )

    // viewDidAppear打印结果
     keywindow; layer = >---
     (
        "; layer = >"
    )
    ```


你可能感兴趣的:(UIWindow)