UIWindows简介


UIWindow是一种特殊的UIView,通常在一个程序中只会有一个UIWindow,但可以手动创建多个UIWindow,同时加到程序里面。UIWindow在程序中主要起到三个作用:

  1. 作为容器,包含app所要显示的所有视图
  2. 传递触摸消息到程序中view和其他对象
  3. 与UIViewController协同工作,方便完成设备方向旋转的支持

1. 看一下UIwindow的文档:

NOTE

  1. 当使用 storyboard 时,已经自动帮你创建Windows对象了
  2. 当你使用 Interface Builder 时,需要在Launch option中设置全屏( Full Screen )选项
  3. 和创建UIView不同,UIWindow一旦被创建,它就自动地被添加到整个界面上了(UIWindow实例没能正常显示的原因是因为Window的hidden默认值为true,或者level不够高)

Configuring Windows

  • @property(nonatomic) UIWindowLevel windowLevel
    • UIWindow在显示的时候会根据UIWindowLevel进行排序的,即Level高的将排在所有Level比他低的层级的前面。
    • 默认为 0.0
    • 还有三个特殊值:
      • UIKIT_EXTERN const UIWindowLevel UIWindowLevelNormal; 0.000000
      • UIKIT_EXTERN const UIWindowLevel UIWindowLevelAlert; 2000.000000
      • UIKIT_EXTERN const UIWindowLevel UIWindowLevelStatusBar __TVOS_PROHIBITED; 1000.000000
  • @property(nonatomic, strong) UIScreen *screen
    • 显示当前Window的UIScreen对象
    • 默认一般只有唯一的设备屏幕 (mac可以外接显示器,手机行吗?)
  • @property(nonatomic, strong) UIViewController *rootViewController
    • 默认为nil,(代码创建 或者使用 interface builder都可以为它赋值)
    • 若当前window已经保持了一个 view树,设置新值时,旧view树会被移除

Making Windows Key

  • @property(nonatomic, readonly, getter=isKeyWindow) BOOL keyWindow
    • 判断该windows是否是应用的keyWindow
    • keyWindow 能接收键盘或者其他 non-touch相关事件
    • 只有一个windows能作为keywindow
  • - (void)makeKeyAndVisible
    • 使Window成为 key windows,并且在相同或者低level之前展示
  • - (void)becomeKeyWindow
    • 当window成为 key window 时,该方法会被调用
    • 同时会发送 UIWindowDidBecomeKeyNotification 到默认通知中心
    • 不要自己直接调用这个方法
  • - (void)makeKeyWindow
  • - (void)resignKeyWindow
    • 与 becomeKeyWindow 相对应,当window让出 keywindow 时会被调用
    • 会发送 UIWindowDidResignKeyNotification 到默认通知中心

Converting Coordinates

// 跳过

Sending Events

  • - (void)sendEvent:(UIEvent *)event
    • UIApplication 对象将分派事件 发送到相应的views ?

2. 获取UIwindow

2.1获取UIWindow列表

[UIApplication sharedApplication].windows  

获取在应用中打开的UIWindow列表,可以获取应用中的任何一个UIView对象,例如 当输入文字时,弹出的键盘就是UIWindow,如果需要改变键盘的样式,则可用更改当前Window

2.2获取当前主窗口

[UIApplication sharedApplication].keyWindow

获取应用程序的主窗口,用来接收键盘以及非触摸类的消息事件的UIWindow,而且程序中每个时刻只能有一个UIWindow是keyWindow。

注意:如果UIWindow内部的文本框不能输入文字,可能是因为这个UIWindow不是keyWindow

2.3获取当前view 所在的UIWindow

view.window

获得某个UIView所在的UIWindow

3. 把view添加到uiwindow

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

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

     [self.window  addsubview:vc.view];
    
  2. 设置uiwindow的根控制器,自动将rootviewcontroller的view添加到window中,负责管理rootviewcontroller的生命周期

     [self.window.rootviewcontroller=vc];
    

3.1两个方法的区别:

以后的开发中,建议使用(2).因为方法(1)存在一些问题,比如说控制器上面可能由按钮,需要监听按钮的点击事件,如果是1,那么按钮的事件应该由控制器来进行管理。但控制器是一个局部变量,控制器此时已经不存在了,但是控制器的view还在,此时有可能会报错。注意:方法执行完,这个控制器就已经不存在了。

问题描述1:当view发生一些事件的时候,通知控制器,但是控制器已经销毁了,所以可能出现未知的错误。

问题描述2:添加一个开关按钮,让屏幕360度旋转(两者的效果不一样)。当发生屏幕旋转事件的时候,UIapplication对象会将旋转事件传递给uiwindow,uiwindow又会将旋转事件传递给它的根控制器,由根控制器决定是否需要旋转

UIapplication->uiwindow->根控制器(第一种方式没有根控制器,所以不能跟着旋转)。

提示:不通过控制器的view也可以做开发,但是在实际开发中,不要这么做,不要直接把view添加到UIWindow上面去。因为,难以管理

4. 那么在哪些场合会涉及到“手工创建UIWindow”呢?

参考唐巧在《iOS开发进阶》里的描述,我认为支付宝钱包等App的密码保护页面是基于UIWindow实现的,当用户从应用的任何界面按Home键退出,过一段时间再从后台切换回来时,显示一个密码输入界面。只有用户输入了正确的密码,才能进入退出前的界面。因为这个密码输入界面可能从任何应用界面弹出,并且需要盖住所有界面的最上层,所以很合适做一个UIWindow来实现。

其他适合用UIWindow来实现的功能还包括:应用的启动介绍页,应用内的通知提醒消息,应用内的弹出框广告等。

5.在有storyboard的项目中,UIWindow是如何创建的?

有storyboard的项目中的创建过程:

当用户点击应用程序图标的时候,先执行Main函数,执行UIApplicationMain(),根据其第三个和第四个参数创建Application,创建代理,并且把代理设置给application(看项目配置文件info.plist里面的storyboard的name,根据这个name找到对应的storyboard),开启一个事件循环,当程序加载完毕,

他会调用代理的didFinishLaunchingWithOptions:方法。在调用didFinishLaunchingWithOptions:方法之前,会加载storyboard,在加载的时候创建一个window,接下来会创建箭头所指向的控制器,把该控制器设置为UIWindow的根控制器,接下来再将window显示出来,即看到了运行后显示的界面。(提示:关于这部分可以查看story的初始化的文档)

posted @ 2016-04-27 19:20  孙焱焱  阅读(437)  评论(0编辑  收藏  举报