iOS 中的UIWindow
使用Xcode新建一个工程后,Xcode会自动新建一些文件,其中有AppDelegate.h,AppDelegate.m,ViewController.h,ViewController.m,Main.storyboard。AppDelegate.h中有一个对象是UIWindow,代码如下:
@property (strong, nonatomic) UIWindow *window;
那么,这个window的作用是什么呢?
实际上,一个app之所以能够显示在屏幕上,就是因为有该UIWindow对象。只有UIWindow能够主动显示,其他的view可以添加到UIWindow上,这样,其他的view也得以显示在屏幕上。
虽然在Xcode7中已经不能新建一个没有storyboard的工程,但是我们可以通过修改程序的Main Interface来测试UIWindow。方法如下:
点击工程->General,将Main Interface 改为空。如下图:
这时候再运行程序,会发现整个屏幕黑屏,如下图:
黑屏的原因就是因为没有实现UIWindow。
现在,手动实现下UIWindow。
在AppDelegate.m中添加window的代码:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; self.window.backgroundColor = [UIColor whiteColor]; [self.window makeKeyAndVisible]; return YES; }
此时运行程序会发现有错误,错误提示如下:
'NSInternalInconsistencyException', reason: 'Application windows are expected to have a root view controller at the end of application launch'
提示没有rootViewController。也就是说,需要设置UIWindow对象的rootViewController。
设置UIWindow的rootViewController代码如下:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; self.window.backgroundColor = [UIColor whiteColor]; [self.window makeKeyAndVisible]; // 设置rootViewController ViewController *controller = [[ViewController alloc] init]; self.window.rootViewController = controller; return YES; }
运行程序,会看到和没有修改Main Interface 之前是一样的。
我们知道,在app程序启动后,会立刻调用
(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
方法,在该方法中可以设置 UIWindow和UIWindow 的 rootViewController。这样,整个app就显示在屏幕上。
在Xcode中新建工程时,通常情况下会包含 storyboard 文件,此时是不需要在上面的方法中设置 UIWindow的。那么,在有storyboard文件的情况下,是如何设置UIWindow的呢?
实际上,程序在加载主要storyboard的时候(也就是Main Interface 指向的storyboard),就会设置UIWindow和UIWindow的rootViewController。
总结下一个app程序的启动过程:
1: 调用 main 方法
2:调用 UIApplicationMain方法,在该方法中会做下面两件事:
(1)创建UIApplication对象
(2)创建UIApplication的delegate对象
3.1 在没有storyboard的情况下,delegate对象开始监听系统事件:
(1)程序启动完毕的时候,就会调用 application:didFinishLaunchingWithOptions 方法
(2)在 application:didFinishLaunchingWithOptions 方法中创建UIWindow
(3)创建和设置UIWindow的rootViewController
(4)显示创库
3.2 在有storyboard的情况下,根据Info.plist获得最主要的storyboard的文件名,加载最主要的storyboard:
(1)创建UIWindow
(2)创建和设置UIWindow的rootViewController
(3)显示窗口