UIWindow简介
UIWindow是一种特殊的UIView,通常在一个app中只会有一个UIWindow。
iOS程序启动完毕后,创建的第一个视图控件就是UIWindow,接着创建控制器的view,最后将控制器的view添加到UIWindow上,于是控制器的view就显示在屏幕上了。
一个iOS程序之所以能显示到屏幕上,完全是因为它有UIWindow
也就说,没有UIWindow,就看不见任何UI界面。
主窗口
一个应用程序只能有一个主窗口,UIWindow通过以下方法成为主窗口:
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 创建主窗口</span> - (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>)makeKeyWindow; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 创建主窗口并使其显示(其他UIView没有这个方法,这个方法是UIWindow能显示的根源)</span> - (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>)makeKeyAndVisible; </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>
真正的主窗口为最后一个调用以上两个方法中其中一个的UIWindow。
注意:
ios7以前,只有主窗口才能响应键盘输入,次窗口无法进行输入,ios7以后,主次窗口都能进行输入。
根控制器
<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@property</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">nonatomic</span>,retain) <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIViewController</span> *rootViewController </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>
添加UIView到UIWindow的两种常见方式:
<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 直接将view添加到UIWindow中,但并不会理会view对应的UIViewController</span> - (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>)addSubview:(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIView</span> *)view; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 自动将rootViewController的view添加到UIWindow中,负责管理rootViewController的生命周期</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@property</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">nonatomic</span>,retain) <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIViewController</span> *rootViewController;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>
推荐使用第二种,原因:
第一种的问题:
- 当view发生一些事件的时候,通知控制器, 但是控制器已经销毁了,所以可能出现未知错误
- 发生旋转事件的时候 UIApplication对象会将旋转事件传递给UIWindow,UIWindow又会将旋转事件传递它的根控制器,由根控制器决定是否需要旋转,即:
UIApplication->UIWindow->根控制器
但此时是没有根控制器的,所以UIView上面的子控件无法进行旋转。
获得UIWindow
<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">[<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIApplication</span> sharedApplication]<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.windows</span> 在本应用中打开的<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIWindow</span>列表,这样就可以接触应用中的任何一个<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIView</span>对象(平时输入文字弹出的键盘,就处在一个新的<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIWindow</span>中) [<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIApplication</span> sharedApplication]<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.keyWindow</span> 用来接收键盘以及非触摸类的消息事件的<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIWindow</span>,而且程序中每个时刻只能有一个<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIWindow</span>是keyWindow。如果某个<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIWindow</span>内部的文本框不能输入文字,可能是因为这个<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIWindow</span>不是keyWindow view<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.window</span> 获得某个<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIView</span>所在的<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIWindow</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul>
创建UIWindow
1、在没有storyboard的情况下,创建UIWindow在AppDelegate(遵守UIApplicationDelegate协议的对象)代理方法中
<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 程序启动完毕之后就会调用一次</span> - (<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">BOOL</span>)application:(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIApplication</span> *)application didFinishLaunchingWithOptions:(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSDictionary</span> *)launchOptions</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>
创建示例代码:
<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.window</span> = [[<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIWindow</span> alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIViewController</span> *vc = [[<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIViewController</span> alloc] init]; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.window</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.rootViewController</span> = vc; [<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.window</span> makeKeyAndVisible];</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>
2、在有storyboard的情况下,xcode会自动创建UIWindow,并去storyboard文件下获取箭头指向的UIViewController作为根控制器(这些步骤是在…didFinishLaunching…方法之前完成的,在…didFinishLaunching…方法中可打印出获取的根控制器)。
四大对象关系图