一、UIApplicationDelegate是什么?
每个 iPhone 应用程序都有一个 UIApplication,UIApplication 是 iPhone 应用程序的开始并且负责初始化并显示 UIWindow,并负责加载应用程序的第一个 UIView 到 UIWindow 窗体中。
UIApplication 的另一个任务是帮助管理应用程序的生命周期,而 UIApplication 通过一个名字为 UIApplicationDelegate 的代理类来履行这个任务。尽管 UIApplication 会负责接收事件,而 UIApplicationDelegate 则决定应用程序如何去响应这些事件,UIApplicationDelegate 可以处理的事件包括应用程序的生命周期事件(比如程序启动和关闭)、系统事件(比如来电、记事项警 告)。如下图:
通常是没必要修改UIApplication的,只需要知道 UIApplication 接收系统事件即可。处理系统事件需要编写一个继承自 UIApplicationDelegate 接口的类,而 UIApplicationDelegate 接口提供生命周期函数来处理应用程序以及应用程序的系统事件。我们新建项目的时候,往往会自动生成一个继承自 UIApplicationDelegate 接口的类AppDelegate。
二、UIApplicationDelegate的生命周期
下面通过一个小demo理解UIApplicationDelegate常用生命周期中的方法:
#pragma mark 在应用程序加载完毕之后调用
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSLog(@"didFinishLaunchingWithOptions-加载完毕");
// 初始化一个窗口
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// 传入xib文件名来初始化一个控制器
self.viewController = [[[MJViewController alloc] initWithNibName:@"MJViewController" bundle:nil] autorelease];
// 设置窗口的根控制器
self.window.rootViewController = self.viewController;
// 上面的代码内部执行了下面代码的操作
// [self.window addSubview:self.viewController.view];
// 窗口不会默认显示,需要调用方法来显示
// keyWindow是主窗口,只有主窗口才能跟用户正常交互
[self.window makeKeyAndVisible];
// self.window.hidden = NO;
return YES;
}
#pragma mark 程序失去焦点的时候调用(不能跟用户进行交互了)
- (void)applicationWillResignActive:(UIApplication *)application
{
NSLog(@"applicationWillResignActive-失去焦点");
}
#pragma mark 当应用程序进入后台的时候调用(点击HOME键)
- (void)applicationDidEnterBackground:(UIApplication *)application
{
NSLog(@"applicationDidEnterBackground-进入后台");
}
#pragma mark 当应用程序进入前台的时候调用
- (void)applicationWillEnterForeground:(UIApplication *)application
{
NSLog(@"applicationWillEnterForeground-进入前台");
}
#pragma mark 当应用程序获取焦点的时候调用
// 获取焦点之后才可以跟用户进行交互
- (void)applicationDidBecomeActive:(UIApplication *)application
{
NSLog(@"applicationDidBecomeActive-获取焦点");
}
#pragma mark 程序在某些情况下被终结时会调用这个方法
- (void)applicationWillTerminate:(UIApplication *)application
{
NSLog(@"applicationWillTerminate-被关闭");
}
项目启动后:
Test[517:c07] didFinishLaunchingWithOptions-加载完毕
Test[517:c07] applicationDidBecomeActive-获取焦点
按下home键:
Test[517:c07] applicationWillResignActive-失去焦点
Test[517:c07] applicationDidEnterBackground-进入后台
再按程序:
Test[517:c07] applicationWillEnterForeground-进入前台
Test[517:c07] applicationDidBecomeActive-获取焦点
三、UIViewController是什么
UIViewController(后面简称ViewController)是iOS开发中MVC模式中的C,ViewController是view的controller,ViewController的职责主要包括管理内部各个view的加载显示和卸载,同时负责与其他ViewController的通信和协调。
在IOS中,有两类ViewController,一类是显示内容的,比如UIViewController、UITableViewController等,同时还可以自定义继承自UIViewController的ViewController;另一类是ViewController容器,UINavigationViewController和UITabBarController等,UINavigationController是以Stack的形式来存储和管理ViewController,UITabBarController是以Array的形式来管理ViewController。和Android中Activity一样,IOS开发中,ViewController也有自己的生命周期。
四、UIViewController的生命周期
1、view的加载和卸载
既然ViewController负责管理内部各个view的加载显示和卸载,那我们先来看看View的加载过程,如下图:
从图中可以看到,在view加载过程中首先会调用loadView方法,在这个方法中主要完成一些关键view的初始化工作,比如UINavigationViewController和UITabBarController等容器类的ViewController;
接下来就是加载view,加载成功后,会接着调用viewDidLoad方法,这里要记住的一点是,在loadView之前,是没有view的,也就是说,在这之前,view还没有被初始化。完成viewDidLoad方法后,ViewController里面就成功的加载view了,如上图右下角所示。
在Controller中创建view有两种方式,一种是通过代码创建、一种是通过Storyboard或Interface Builder来创建,后者可以比较直观的配置view的外观和属性,Storyboard配合IOS6后推出的AutoLayout,应该是Apple之后主推的一种UI定制解决方案。
接下来我们看看ViewController中的view是如何被卸载的,如下图:
从图中可以看到,当系统发出内存警告时,会调用didReceiveMemoeryWarning方法,如果当前有能被释放的view,系统会调用viewWillUnload方法来释放view,完成后调用viewDidUnload方法,至此,view就被卸载了。此时原本指向view的变量要被置为nil,具体操作是在viewDidUnload方法中调用self.myView = nil;
2、ViewController的生命周期
ViewController的生命周期中各方法执行流程如下图:
例如:
@interface ViewController ()
@end
@implementation ViewController
- (instancetype)init
{
self = [super init];
if (self) {
NSLog(@"ViewController 初始化");
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
NSLog(@"ViewController 从归档初始化");
}
return self;
}
- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.view.backgroundColor = [UIColor whiteColor];
NSLog(@"ViewController 从xib初始化");
}
return self;
}
- (void)loadView {
[super loadView];
NSLog(@"ViewController 开始加载视图");
}
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"ViewController 已经加载视图");
}
- (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
NSLog(@"ViewController 开始布局子视图");
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
NSLog(@"ViewController 完成布局子视图");
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSLog(@"ViewController 即将显示");
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSLog(@"ViewController 已经显示");
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
NSLog(@"ViewController 即将消失");
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
NSLog(@"ViewController 已经消失");
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
NSLog(@"ViewController 收到内存警告");
}
@end
打印结果:
2017-01-11 12:02:55.422 Test[11948:560350] ViewController 从归档初始化
2017-01-11 12:02:55.433 Test[11948:560350] ViewController 开始加载视图
2017-01-11 12:02:55.434 Test[11948:560350] ViewController 已经加载视图
2017-01-11 12:02:55.434 Test[11948:560350] ViewController 即将显示
2017-01-11 12:02:55.440 Test[11948:560350] ViewController 开始布局子视图
2017-01-11 12:02:55.440 Test[11948:560350] ViewController 完成布局子视图
2017-01-11 12:02:55.443 Test[11948:560350] ViewController 已经显示
原创文章,转载请注明: 转载自李峰峰博客