深入了解iOS开发中UIWindow的相关使用
UIWindow是一种特殊的UIView,通常在一个app中只会有一个UIWindow。
iOS程序启动完毕后,创建的第一个视图控件就是UIWindow,接着创建控制器的view,最后将控制器的view添加到UIWindow上,于是控制器的view就显示在屏幕上了。
一个iOS程序之所以能显示到屏幕上,完全是因为它有UIWindow。也就说,没有UIWindow,就看不见任何UI界面。
如何获取UIWindow
(1)[UIApplicationsharedApplication].windows 在本应用中打开的UIWindow列表,这样就可以接触应用中的任何一个UIView对象(平时输入文字弹出的键盘,就处在一个新的UIWindow中);
(2)[UIApplicationsharedApplication].keyWindow(获取应用程序的主窗口)用来接收键盘以及非触摸类的消息事件的UIWindow,而且程序中每个时刻只能有一个UIWindow是keyWindow;
注:经过代码验证,非keyWindow也是可以接受键盘消息的;
提示:如果某个UIWindow内部的文本框不能输入文字,可能是因为这个UIWindow不是keyWindow;
(3)view.window获得某个UIView所在的UIWindow。
UIWindowLevel
我们知道UIWindow有三个层级,分别是Normal,StatusBar,Alert.输出他们三个层级的值,我们发现从左到右依次是0,1000,2000,也就是说Normal级别是最低的,StatusBar处于中级,Alert级别最高。而通常我们的程序的界面都是处于Normal这个级别的,系统顶部的状态栏应该是处于StatusBar级别,UIActionSheet和UIAlertView这些通常都是用来中断正常流程,提醒用户等操作,因此位于Alert级别。
根据window显示级别优先原则,级别高的会显示在最上层,级别低的在下面,我们程序正常显示的view在最底层;
keyWindow
官方文档中是这样解释的“Thekeywindowistheonethatisdesignatedtoreceivekeyboardandothernon-touchrelatedevents.Onlyonewindowatatimemaybethekeywindow."翻译过来就是说,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
iOS8开始UIWindow的bounds发生变化(Window本身发生了旋转)
iOS7之前Window的bounds不会随着方向而变化,但是到了iOS8以后,随着设备方向的旋转,window.bounds.size.width和window.bounds.size.height也会相应发生变化。
做个很简单的测试,代码如下:
-(BOOL)application:(UIApplication*)applicationdidFinishLaunchingWithOptions:(NSDictionary*)launchOptions{ //Overridepointforcustomizationafterapplicationlaunch. [[NSNotificationCenterdefaultCenter]addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil]; returnYES; }
-(void)orientationChanged:(NSNotification*)noti{ UIDeviceOrientationorientation=[UIDevicecurrentDevice].orientation; NSString*orientationDes=nil; switch(orientation){ caseUIDeviceOrientationLandscapeLeft: orientationDes=@"UIInterfaceOrientationLandscapeRight"; break; caseUIDeviceOrientationLandscapeRight: orientationDes=@"UIInterfaceOrientationLandscapeLeft"; break; caseUIDeviceOrientationPortrait: orientationDes=@"UIInterfaceOrientationPortrait"; break; caseUIDeviceOrientationPortraitUpsideDown: orientationDes=@"UIInterfaceOrientationPortraitUpsideDown"; break; default: orientationDes=@""; break; } NSLog(@"systemver:%@,\rorientaion:%@,\rwindowbounds:%@", [UIDevicecurrentDevice].systemVersion, orientationDes, NSStringFromCGRect(self.window.bounds)); }