分析UIWindow
The UIWindow class defines an object known as a window that manages and coordinates the views an app displays on a device screen. Unless an app can display content on an external device screen, an app has only one window.
UIWindow定义了一个对象,用来管理视图的坐标系统,除非,app可以在另外一个窗口里面展示内容,否则,一个app只有一个window.
每一个controller都会被UIWindow接管,UIWindow一次只能接管一个controller,下面用代码验证.
首先,我们来看看,UIWindow何时接管了controller.
请写以下代码:
// // RootViewController.m // Window // // Copyright (c) 2014年 Y.X. All rights reserved. // #import "RootViewController.h" @interface RootViewController () @end @implementation RootViewController - (void)viewDidLoad { [super viewDidLoad]; if (self.view.window) { NSLog(@"viewDidLoad"); NSLog(@"%@", NSStringFromCGRect(self.view.window.frame)); } } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; if (self.view.window) { NSLog(@"viewWillAppear"); NSLog(@"%@", NSStringFromCGRect(self.view.window.frame)); } } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; if (self.view.window) { NSLog(@"viewDidAppear"); NSLog(@"%@", NSStringFromCGRect(self.view.window.frame)); } } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; if (self.view.window) { NSLog(@"viewWillDisappear"); NSLog(@"%@", NSStringFromCGRect(self.view.window.frame)); } } - (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; if (self.view.window) { NSLog(@"viewDidDisappear"); NSLog(@"%@", NSStringFromCGRect(self.view.window.frame)); } } @end
打印信息,注意哦,UIWindow会在一个controller的viewDidAppear方法中才接管了当前controller,而不是在ViewDidLoad方法中,注意:)
接下来,我们在导航栏控制器间切换,来观察,UIWindow如何放弃一个controller然后接管另外一个controller
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Override point for customization after application launch. UINavigationController *NC = \ [[UINavigationController alloc] initWithRootViewController:[RootViewController new]]; self.window.rootViewController = NC; self.window.backgroundColor = [UIColor whiteColor]; [self.window makeKeyAndVisible]; return YES; }
// // RootViewController.m // Window // // Copyright (c) 2014年 Y.X. All rights reserved. // #import "RootViewController.h" #import "SecondViewController.h" #import "YXGCD.h" @interface RootViewController () @end @implementation RootViewController - (void)viewDidLoad { [super viewDidLoad]; if (self.view.window) { NSLog(@"viewDidLoad"); NSLog(@"%@", NSStringFromCGRect(self.view.window.frame)); } [[GCDQueue mainQueue] execute:^{ [self.navigationController pushViewController:[SecondViewController new] animated:YES]; } afterDelay:NSEC_PER_SEC * 4]; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; if (self.view.window) { NSLog(@"viewWillAppear"); NSLog(@"%@", NSStringFromCGRect(self.view.window.frame)); } } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; if (self.view.window) { NSLog(@"viewDidAppear"); NSLog(@"%@", NSStringFromCGRect(self.view.window.frame)); } } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; if (self.view.window) { NSLog(@"viewWillDisappear"); NSLog(@"%@", NSStringFromCGRect(self.view.window.frame)); } } - (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; if (self.view.window) { NSLog(@"viewDidDisappear"); NSLog(@"%@", NSStringFromCGRect(self.view.window.frame)); } } @end
// // SecondViewController.m // Window //// Copyright (c) 2014年 Y.X. All rights reserved. // #import "SecondViewController.h" @interface SecondViewController () @end @implementation SecondViewController - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor redColor]; } @end
查看结果:
结论很自然,一个UIWindow只能在接管一个controller.
为什么要纠结于UIWindow的这些小细节呢?因为,UIWindow有着比一切controller都要高的优先级显示权利,加载在UIWindow上面的View是不会被遮挡住的.
效果(注意查看上面的导航条的地方,也被遮盖住了):
源码:
// // RootViewController.m // Window // // Copyright (c) 2014年 Y.X. All rights reserved. // #import "RootViewController.h" #import "YXGCD.h" @interface RootViewController () @end @implementation RootViewController - (void)viewDidLoad { [super viewDidLoad]; [[GCDQueue mainQueue] execute:^{ UIView *redView = [[UIView alloc] initWithFrame:self.view.window.frame]; redView.backgroundColor = [UIColor redColor]; redView.alpha = 0.f; [self.view.window addSubview:redView]; [UIView animateWithDuration:1 animations:^{ redView.alpha = 1.f; } completion:^(BOOL finished) { [UIView animateWithDuration:1 animations:^{ redView.alpha = 0.f; } completion:^(BOOL finished) { [redView removeFromSuperview]; }]; }]; } afterDelay:NSEC_PER_SEC * 10]; } @end
普通的View的加载的效果(注意上方的导航栏,它并没有变成红色):
// // RootViewController.m // Window // // Copyright (c) 2014年 Y.X. All rights reserved. // #import "RootViewController.h" #import "YXGCD.h" @interface RootViewController () @end @implementation RootViewController - (void)viewDidLoad { [super viewDidLoad]; [[GCDQueue mainQueue] execute:^{ UIView *redView = [[UIView alloc] initWithFrame:self.view.window.frame]; redView.backgroundColor = [UIColor redColor]; redView.alpha = 0.f; [self.view addSubview:redView]; [UIView animateWithDuration:1 animations:^{ redView.alpha = 1.f; } completion:^(BOOL finished) { [UIView animateWithDuration:1 animations:^{ redView.alpha = 0.f; } completion:^(BOOL finished) { [redView removeFromSuperview]; }]; }]; } afterDelay:NSEC_PER_SEC * 10]; } @end
其实呢,你如果写成这样子,也是可以遮盖导航条的呢:
其实,就这么多东西:)