UIWindow的一些基本概念和注意点
2016-01-02 20:33
274 查看
1.什么是UIWindow?
UIWindow是一种特殊的UIView,通常在一个app中只会有一个UIWindow
iOS程序启动完毕后,创建的第一个视图控件就是UIWindow,接着创建控制器的view,最后将控制器的view添加到UIWindow上,于是控制器的view就显示在屏幕上了
一个iOS程序之所以能显示到屏幕上,完全是因为它有UIWindow。也就说,没有UIWindow,就看不见任何UI界面
2.如何获取UIWindow?
(1)[UIApplication sharedApplication].windows 在本应用中打开的UIWindow列表,这样就可以接触应用中的任何一个UIView对象(平时输入文字弹出的键盘,就处在一个新的UIWindow中)
(2)[UIApplication sharedApplication].keyWindow(获取应用程序的主窗口)用来接收键盘以及非触摸类的消息事件的UIWindow,而且程序中每个时刻只能有一个UIWindow是keyWindow。
提示:如果某个UIWindow内部的文本框不能输入文字,可能是因为这个UIWindow不是keyWindow
(3)view.window获得某个UIView所在的UIWindow
3.如何把view添加到UIWindow
(1)直接将控制器的view添加到UIWindow中,并不理会它对应的控制器
[self.window addsubview:vc.view];
(2)设置uiwindow的根控制器,自动将rootviewcontroller的view添加到window中,负责管理rootviewcontroller的生命周期
[self.window.rootviewcontroller=vc];
两个方法的区别:
建议使用(2)
因为方法(1)存在一些问题,比如说控制器上面可能由按钮,需要监听按钮的点击事件,如果是1,那么按钮的事件应该由控制器来 进行管理。但控制器是一个局部变量,控制器此时已经不存在了,但是控制器的view还在,此时有可能会报错。
注意: 方法执行完,这个控制器就已经不存在了。
问题描述1: 当view发生一些事件的时候,通知控制器,但是控制器已经销毁了,所以可能出现未知的错误。
问题描述2: 添加一个开关按钮,让屏幕360度旋转(两者的效果不一样)。
当发生屏幕旋转事件的时候,UIapplication对象会将旋转事件传递给uiwindow,uiwindow又会将旋转事件传递给它的根控制器,由根控制器决定是否需要旋转
UIapplication->uiwindow->根控制器(第一种方式没有根控制器,所以不能跟着旋转)。
提示:不通过控制器的view也可以做开发,但是在实际开发中,不要这么做,不要直接把view添加到UIWindow上面去。因为,难以管理。
4.什么是UIWindowLevel?
UIWindow在显示的时候会根据UIWindowLevel进行排序的,即Level高的将排在所有Level比他低的层级的前面
我们知道UIWindow 有三个层级,分别是Normal ,StatusBar,Alert.输出他们三个层级的值,我们发现从左到右依次是0,1000,2000,也就是说Normal级别是最低的,StatusBar处于中级,Alert级别最高。而通常我们的程序的界面都是处于Normal这个级别的,系统顶部的状态栏应该是处于StatusBar级别,UIActionSheet和UIAlertView这些通常都是用来中断正常流程,提醒用户等操作,因此位于Alert级别。
根据window显示级别优先原则,级别高的会显示在最上层,级别低的在下面,我们程序正常显示的view在最底层;
5.keyWindow
keyWindow是指定的用来接收键盘以及非触摸类的消息,而且程序中每一个时刻只能有一个window是keyWindow。
观察UIWindow的文档,我们可以发现里面有四个关于window变化的通知:
UIWindowDidBecomeVisibleNotification
UIWindowDidBecomeHiddenNotification
UIWindowDidBecomeKeyNotification
UIWindowDidResignKeyNotification
这四个通知对象中的object都代表当前已显示(隐藏),已变成keyWindow(非keyWindow)的window对象,其中的userInfo则是空的。
于是我们可以注册这个四个消息,再打印信息来观察keyWindow的变化以及window的显示,隐藏的变动变成keywindow 的流程是这样的
1.程序默认的window先显示出来
2.默认的window再变成keywindow
3.AlertView 的window显示出来
4.默认的window变成keywindow
5.最终AlertView的window变成keywindow
总体来说就是“要想当老大(keyWindow),先从小弟(非keyWindow)开始混起” 而且根据测试我们同时可以知道默认的window的level是0,即normal级别;AlertView的window的level是1996,比Alert级别稍微低了一点儿。
keyWindow的变化和window的显示和上面的流程一样,同时我们可以看出ActionSheet的window的level是2001;
当我们点击ActionSheet cancel的时候,我们会看到流程
1.首先ActionSheet 的window变成非keyWindow
2.程序默认的window变成keywindow
3.ActionSheet 的window隐藏掉
拓展:
@property(nonatomic,readonly) NSArray *windows;跟keywindow
刚开始看了觉得很奇怪,不是说一个应用只有一个窗口吗?干嘛还弄个数组,结果一测试才知道输出来以后,除了window还有UITextEffetsWindow。网上查了keywindow是指当前活跃的window,与用户交互的window。而windows是指当前app打开的所有window,比如键盘也在一个window里面,alert也在一个window里面。在windows数组里面,window是根据windowLevel来排列的,最后一个覆盖在最上面。这里的windows数组不包括系统提供的window,比如说状态栏就是在一个系统创建的window里面
注意:keyWindow不是一成不变的,当你创建alertView或者ActionSheet的时候,它们所在的window会变成keyWindow。也就是说系统默认创建的window首先变成keywindow,而当弹框的时候,alertView所在的window变成keywindow,默认的keywindow变成非key window。
注意:
1.在使用[[UIApplication shareApplication] keyWindow] 方法调用KeyWindow时 拿到的UIWindow有可能是nil.
这时因为当在执行
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
里执行 makeKeyAndVisible 的时候,他会调用第一个VC的viewDidLoad 方法,在那里面调用 keyWindow就无法取到UIWindow, 因为makeKeyAndVisible没有执行完。
2.从iOS9开始,Xcode7需要所有UIWindow必须有一个rootViewController,否则报以上错误。
Xcode7出现:
Assertion failure in -[UIApplication _runWithMainScene:transitionContext:completion:]
UIWindow是一种特殊的UIView,通常在一个app中只会有一个UIWindow
iOS程序启动完毕后,创建的第一个视图控件就是UIWindow,接着创建控制器的view,最后将控制器的view添加到UIWindow上,于是控制器的view就显示在屏幕上了
一个iOS程序之所以能显示到屏幕上,完全是因为它有UIWindow。也就说,没有UIWindow,就看不见任何UI界面
2.如何获取UIWindow?
(1)[UIApplication sharedApplication].windows 在本应用中打开的UIWindow列表,这样就可以接触应用中的任何一个UIView对象(平时输入文字弹出的键盘,就处在一个新的UIWindow中)
(2)[UIApplication sharedApplication].keyWindow(获取应用程序的主窗口)用来接收键盘以及非触摸类的消息事件的UIWindow,而且程序中每个时刻只能有一个UIWindow是keyWindow。
提示:如果某个UIWindow内部的文本框不能输入文字,可能是因为这个UIWindow不是keyWindow
(3)view.window获得某个UIView所在的UIWindow
3.如何把view添加到UIWindow
(1)直接将控制器的view添加到UIWindow中,并不理会它对应的控制器
[self.window addsubview:vc.view];
(2)设置uiwindow的根控制器,自动将rootviewcontroller的view添加到window中,负责管理rootviewcontroller的生命周期
[self.window.rootviewcontroller=vc];
两个方法的区别:
建议使用(2)
因为方法(1)存在一些问题,比如说控制器上面可能由按钮,需要监听按钮的点击事件,如果是1,那么按钮的事件应该由控制器来 进行管理。但控制器是一个局部变量,控制器此时已经不存在了,但是控制器的view还在,此时有可能会报错。
注意: 方法执行完,这个控制器就已经不存在了。
问题描述1: 当view发生一些事件的时候,通知控制器,但是控制器已经销毁了,所以可能出现未知的错误。
问题描述2: 添加一个开关按钮,让屏幕360度旋转(两者的效果不一样)。
当发生屏幕旋转事件的时候,UIapplication对象会将旋转事件传递给uiwindow,uiwindow又会将旋转事件传递给它的根控制器,由根控制器决定是否需要旋转
UIapplication->uiwindow->根控制器(第一种方式没有根控制器,所以不能跟着旋转)。
提示:不通过控制器的view也可以做开发,但是在实际开发中,不要这么做,不要直接把view添加到UIWindow上面去。因为,难以管理。
4.什么是UIWindowLevel?
UIWindow在显示的时候会根据UIWindowLevel进行排序的,即Level高的将排在所有Level比他低的层级的前面
我们知道UIWindow 有三个层级,分别是Normal ,StatusBar,Alert.输出他们三个层级的值,我们发现从左到右依次是0,1000,2000,也就是说Normal级别是最低的,StatusBar处于中级,Alert级别最高。而通常我们的程序的界面都是处于Normal这个级别的,系统顶部的状态栏应该是处于StatusBar级别,UIActionSheet和UIAlertView这些通常都是用来中断正常流程,提醒用户等操作,因此位于Alert级别。
根据window显示级别优先原则,级别高的会显示在最上层,级别低的在下面,我们程序正常显示的view在最底层;
5.keyWindow
keyWindow是指定的用来接收键盘以及非触摸类的消息,而且程序中每一个时刻只能有一个window是keyWindow。
观察UIWindow的文档,我们可以发现里面有四个关于window变化的通知:
UIWindowDidBecomeVisibleNotification
UIWindowDidBecomeHiddenNotification
UIWindowDidBecomeKeyNotification
UIWindowDidResignKeyNotification
这四个通知对象中的object都代表当前已显示(隐藏),已变成keyWindow(非keyWindow)的window对象,其中的userInfo则是空的。
于是我们可以注册这个四个消息,再打印信息来观察keyWindow的变化以及window的显示,隐藏的变动变成keywindow 的流程是这样的
1.程序默认的window先显示出来
2.默认的window再变成keywindow
3.AlertView 的window显示出来
4.默认的window变成keywindow
5.最终AlertView的window变成keywindow
总体来说就是“要想当老大(keyWindow),先从小弟(非keyWindow)开始混起” 而且根据测试我们同时可以知道默认的window的level是0,即normal级别;AlertView的window的level是1996,比Alert级别稍微低了一点儿。
keyWindow的变化和window的显示和上面的流程一样,同时我们可以看出ActionSheet的window的level是2001;
当我们点击ActionSheet cancel的时候,我们会看到流程
1.首先ActionSheet 的window变成非keyWindow
2.程序默认的window变成keywindow
3.ActionSheet 的window隐藏掉
拓展:
@property(nonatomic,readonly) NSArray *windows;跟keywindow
刚开始看了觉得很奇怪,不是说一个应用只有一个窗口吗?干嘛还弄个数组,结果一测试才知道输出来以后,除了window还有UITextEffetsWindow。网上查了keywindow是指当前活跃的window,与用户交互的window。而windows是指当前app打开的所有window,比如键盘也在一个window里面,alert也在一个window里面。在windows数组里面,window是根据windowLevel来排列的,最后一个覆盖在最上面。这里的windows数组不包括系统提供的window,比如说状态栏就是在一个系统创建的window里面
注意:keyWindow不是一成不变的,当你创建alertView或者ActionSheet的时候,它们所在的window会变成keyWindow。也就是说系统默认创建的window首先变成keywindow,而当弹框的时候,alertView所在的window变成keywindow,默认的keywindow变成非key window。
注意:
1.在使用[[UIApplication shareApplication] keyWindow] 方法调用KeyWindow时 拿到的UIWindow有可能是nil.
这时因为当在执行
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
里执行 makeKeyAndVisible 的时候,他会调用第一个VC的viewDidLoad 方法,在那里面调用 keyWindow就无法取到UIWindow, 因为makeKeyAndVisible没有执行完。
2.从iOS9开始,Xcode7需要所有UIWindow必须有一个rootViewController,否则报以上错误。
Xcode7出现:
Assertion failure in -[UIApplication _runWithMainScene:transitionContext:completion:]
相关文章推荐
- Starting MySQL...... ERROR! Manager of pid-file quit without updating file.
- UIPageControl
- UIScrollView
- UIView动画
- 182. Duplicate Emails My Submissions Question
- iOS UIPickerView的使用
- UISlider 滑竿控件
- 303,Range Sum Query
- UISegmentControl
- UIButton, UILabel, UITextField
- UISwitch 开关控件
- UEFI不小心误删EPS分区里的grub引导恢复
- 加载EasyUi和使用Parser解析器
- UIView属性
- POJ-3061 Subsequence(尺取法)
- 二分+线段树 Codeforces609F Frogs and mosquitoes
- Java基础之break和continue
- UITableView 滚动流程性优化
- ArrayBlockingQueue 和LinkedBlockingQueue
- BlockingQueue