iOS-UI篇-UIWindow

一. 关于UIWindow

  1. UIWindow是一种特殊的UIView,通常在一个app中只会有一个UIWindow。
  2. iOS程序启动完毕后,创建的第一个视图控件就是UIWindow,接着创建控制器,再创建控制器的view,最后将控制器的view添加到UIWindow上,于是控制器的view就显示在屏幕上了。
  3. 一个iOS程序之所以能显示到屏幕上,完全是因为它有UIWindow,也就是说,没有UIWindow,就看不见任何UI界面。
  4. UIWindow是创建的第一个视图控件,UIapplication是创建的第一个对象。

文档中关于该部分的解释:

UIWindow.png

二. UIWindow的使用

1. 创建window

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
    
    return YES;
}

2. 把view添加到window上

创建一个控制器,把view添加到window上面,有两种方式:

方式1:

直接将控制器的view添加到window中,并不理会它对应的控制器

[self.window addsubview:vc.view];
方式2:推荐

设置window的根控制器,自动将rootviewcontroller的view添加到window中,负责管理rootviewcontroller的生命周期(推荐这种方式)。

[self.window.rootviewcontroller = vc];
方式1的问题:

问题1:当view发生一些事件的时候,通知控制器,但是控制器已经销毁了,所以可能出现未知的错误。比如说控制器上面可能有按钮,需要监听按钮的点击事件,如果是1,那么按钮的事件应该由控制器来进行管理,但控制器是一个局部变量,控制器此时已经不存在了,但是控制器的view还在,此时有可能会报错。

问题2:添加一个开关按钮,让屏幕360度旋转,当发生屏幕旋转事件的时候,UIapplication对象会将旋转事件传递给window,window又会将旋转事件传递给它的根控制器,由根控制器决定是否需要旋转,如下:
UIapplication->UIWindow->根控制器,由于第一种方式没有根控制器,所以不能跟着旋转。

三. UIWindow的创建过程

1. 有storyboard

  1. 为什么创建一个storyboard,没有看到创建window的过程?

它其实是把创建UIWindow的过程给屏蔽起来了。可以把代理的UIWindow的属性的值打印出来:

NSLog(@“window=%p”,self.window);

打印出来确实是有值的,说明确实创建了UIWindow,不仅创建了UIWindow,默认还创建了UIWindow对应的控制器,也可以打印进行查看。

NSLog(@“%@“,self.window.rootviewcontroller);
  1. 有storyboard的项目中的创建过程:

当用户点击应用程序图标的时候,先执行Main函数,执行UIApplicationMain(),根据其第三个和第四个参数创建Application,创建代理,并且把代理设置给application,然后查看项目配置文件info.plist里面的storyboard的name,根据这个name找到对应的storyboard,开启一个事件循环,当程序加载完毕,他会调用代理的didFinishLaunchingWithOptions:方法。在调用didFinishLaunchingWithOptions:方法之前,会加载storyboard,在加载的时候创建一个window,接下来会创建箭头所指向的控制器,把该控制器设置为UIWindow的根控制器,接下来再将window显示出来,即看到了运行后显示的界面。关于这部分可以查看story的初始化的文档:

storyboard.png

2. 没有storyboard

先执行Main函数,执行UIApplicationMain(),根据其第三个和第四个参数创建Application,创建代理,并且把代理设置给application,开启一个事件循环,当程序加载完毕,他会调用代理的didFinishLaunchingWithOptions:方法。在该方法中,会创建一个Window,然后创建一个控制器,并把该控制器设置为UIWindow的根控制器,接下来再将window显示出来,即看到了运行后显示的界面。

四. 主窗口

1. 设置主窗口

[self.window makekeyandvisible] 

让窗口成为主窗口,并且显示出来。有这个方法,才能把信息显示到屏幕上。

因为window有makekeyandvisible这个方法,可以让这个window凭空的显示出来,而其他的view没有这个方法,所以它只能依赖于window,window显示出来后,view才依附在window上显示出来。

一个应用程序中只能有一个主窗口,如果程序中设置了两个主窗口,后面的主窗口能覆盖前面的主窗口。

[self.window make keywindow]

让window成为主窗口,但不显示。

2. 获取window

[UIApplication sharedApplication].windows;

在本应用中打开的UIWindow列表,这样就可以获取应用中的任何一个UIView对象,平时输入文字弹出的键盘,就处在一个新的UIWindow中。

[UIApplication sharedApplication].keyWindow;

获取应用程序的主窗口,而且程序中每个时刻只能有一个window是keyWindow。

UIWindow *viewWindow = view.window;

获得某个UIView所在的UIWindow。

五. UIWindow的用处

在IOS应用中,我们使用UIWindow和UIView来呈现界面。UIWindow并不包含任何默认的内容,它被当做UIView的容器,用于放置应用中所有的UIView。从继承关系来看,UIWindow继承自UIView,所以UIWIndow除了具有UIView的所有功能外,还增加了一些特有的属性和方法。

UIWindow的主要作用:

  1. 作为UIView的最顶层容器,包含应用显示所需要的所有UIView
  2. 传递触摸消息和键盘事件给UIView

关于系统对UIWindow的使用:
通常在一个程序中只会有一个UIWindow,但有些时候我们调用系统的控件(例如UIAlertView)时,IOS系统为了保证UIAlertView在所有的界面之上,它会临时创建一个新的UIWindow,通过将其UIWindow的UIWindowLevel设置的更高,让UIWindow盖在所有的应用界面之上(熟悉html的朋友应该知道,网页上面的“遮罩效果”,就是通过设置元素的z-index属性,来控制层级的上下关系,是一个道理)。

六. 四大对象的关系

四大对象.png

你可能感兴趣的:(iOS-UI篇-UIWindow)