UIWindow
简介
- UIWindow是一种特殊的UIView,特殊在它具有显示功能,普通UIView没有自我显示的功能。
空项目中创建UIWindow
创建控制器,将控制器的view添加到UIWindow上,方法有两种:
1> 直接将控制器的view添加到UIWindow上。
OneViewController *one = [[OneViewController alloc] init];
[self.window addSubview:one.view];
2> 设置window的根控制器为one控制器。
self.window.rootViewController = one;
== 注意:在实际开发中,强烈推荐使用第2种方式。使用第1种方式至少会导致以下两种致命的错误:==
* 由于one控制器是局部变量,在application: didFinishLaunchingWithOptions:方法执行完毕后就销毁了,无法再监听其view内部子控件的任何事件。
* 当window接收到旋转事件时,one内部的内容也不会跟着旋转了。因为one控制器已经不存在。
当发生屏幕旋转事件的时候,UIapplication对象会将旋转事件传递给uiwindow,uiwindow又会将旋转事件传递给它的根控制器,由根控制器决定是否需要旋转
UIapplication->uiwindow->根控制器(第一种方式没有根控制器,所以不能跟着旋转)
由于UIWindow也是一个UIView。所以不需要控制器也能够开发,但不建议这么做,
原因如下:
1> 没有控制器,意味着所有的视图控件都必须添加到UIWindow上,跟视图相关的所有事件都必须交给UIWindow管理,这会导致UIWindow很复杂,管理困难。 2> 在实际开发中从来没有过这样的做法。app一般都会有多个界面,每一个界面交给一个控制器去管理。这是最简单也是最合适的做法。
storyboard创建的UIWindow
加载步骤
加载最主要的stroyboard时候,内部已经创建好了UIWindow对象
然后创建stroyboard里面箭头所指向的控制器和控制器的view
最后会将创建好的控制器设置为UIWindow的根控制器。这时控制器的view也添加到了 window上面。
查看官方文档,验证上面的说法。
The main storyboard is defined in the app’s Information property list file. If a main storyboard is declared in this file, then when your app launches, iOS performs the following steps:1> It instantiates a window for you. 2> It loads the main storyboard and instantiates its initial view controller. 3> It assigns the new view controller to the window’s rootViewController property and then makes the window visible on the screen.
UIWindow中的其他概念
使用局部变量引用窗口,验证window的属性定义为strong,就是为了让其不销毁。
// 1.创建UIWindow
UIWindow *window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
// 2.设置 window 的背景
window.backgroundColor = [UIColor whiteColor];
// 3.显示 window
[window makeKeyAndVisible];
主窗口和次窗口
一个app同一时间只能有一个主窗口,但可以有多个窗口。
最后设置的主窗口会取代之前设置的主窗口成为主窗口。
系统弹出的键盘也是一个窗口。打印窗口数量验证
注意点:
在ios7后,主窗口和次窗口是没有区别的。在ios7之前,只有主窗口才能响应键盘的输入事件,如果不能输入内容,可以查看是否是显示在主窗口上,不在主窗口上的不能响应。
在iOS8后,一旦在屏幕上触发了事件(例如点击按钮,点击控制器的view),系统就会创建一个键盘窗口。这个键盘窗口是看不见的,只有当点击了一个能触发键盘弹出的控件(UITextField),键盘窗口才会显示出来。 这时候打印UIWindow的个数至少有两个。
当点击UITextField后,UITextField已经获得焦点了,但键盘却没有出现。这时可以按快捷键让键command+K盘显示出现。当使用电脑键盘给文本输入框输入内容没有反应时,可以按快捷键command+shift+k来解决。(也可以通过工具栏设置)
程序启动的完整过程
先执行main函数,main内部会调用UIApplicationMain函数,该函数的声明如下:
int UIApplicationMain(int argc, char argv[], NSString principalClassName, NSString *delegateClassName);
argc、argv:标准main函数的参数,直接传递给UIApplicationMain进行相关处理即可
principalClassName:指定应用程序类,该类必须是UIApplication(或子类)。如果为nil,则用UIApplication类作为默认值
delegateClassName:指定应用程序类的代理类,该类必须遵守UIApplicationDelegate协议。
在UIApplicationMain函数里面做了如下几件事情:
> 根据传入的第三个参数创建UIApplication对象或它的子类对象。如果该参数为nil,直接使用该UIApplication来创建。(该参数只能传人UIApplication或者是它的子类)
> 根据传入的第四个参数创建AppDelegate对象,并将该对象赋值给第1步创建的 UIApplication对象的delegate属性。
> 开启一个事件循环,循环监控应用程序发生的事件。每监听到对应的系统事件时,就会通知AppDelegate。
分两种情况:
有stroyboard
> 应用程创建一个UIWindow对象(继承自UIView),并设置为AppDelegate的window属性。
> 加载Info.plist文件,读取最主要storyboard文件的名称。
> 加载最主要的storyboard文件,创建白色箭头所指的控制器对象。并且设置控制器为UIWindow的rootViewController属性(根控制器)。
> 展示UIWindow,展示之前会将添加rootViewController的view到UIWindow上面(在这一步才会创建控制器的view),其内部会执行该行代码:[window addSubview: window.rootViewControler.view];
没有stroyboard
> 首先会调用delegate对象的application:didFinishLaunchingWithOptions:方法。
> 在application:didFinishLaunchingWithOptions:方法中需要主动创建 UIWindow对象。并设置为AppDelegate的window属性。
> 主动创建一个 UIViewController对象,并赋值给window的rootViewController属性。
> 调用 window的makeKeyAndVisible方法显示窗口。