UIApplication Delegate和UIApplicationMain(程序完整启动过程)
一、UIApplication Delegate
1、基本介绍
所有的移动操作系统都有个致命的缺点:app很容易受到打扰。比如一个来电或者锁屏会导致app进入后台甚至被终止。
还有很多其它类似的情况会导致app受到干扰,在app受到干扰时,会产生一些系统事件,这时UIApplication会通知它的delegate对象,让delegate代理来处理这些系统事件。包括:
(1)应用程序的声明周期事件(如程序启动和关闭)
(2)系统事件(如来电)
(3)内存警告
作用:当被打断的时候,通知代理进入到后台。
2、代码
1 #import "AppDelegate.h" 2 3 @interface AppDelegate () 4 5 @end 6 7 @implementation AppDelegate 8 9 // 当应用程序启动完毕的时候就会调用(系统自动调用) 10 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 11 NSLog(@"didFinishLaunchingWithOptions"); 12 return YES; 13 } 14 // 即将失去活动状态的时候调用(失去焦点, 不可交互) 15 - (void)applicationWillResignActive:(UIApplication *)application { 16 NSLog(@"WillResignActive"); 17 } 18 // 应用程序进入后台的时候调用,一般在该方法中保存应用程序的数据, 以及状态。 19 - (void)applicationDidEnterBackground:(UIApplication *)application { 20 NSLog(@"DidEnterBackground"); 21 } 22 // 应用程序即将进入前台的时候调用,一般在该方法中恢复应用程序的数据,以及状态 23 - (void)applicationWillEnterForeground:(UIApplication *)application { 24 NSLog(@"WillEnterForeground"); 25 } 26 // 重新获取焦点(能够和用户交互) 27 - (void)applicationDidBecomeActive:(UIApplication *)application { 28 NSLog(@"DidBecomeActive"); 29 } 30 //应用程序即将被销毁的时候会调用该方法, 31 //注:如果应用程序处于挂起状态(程序未处于运行状态,但也没有被结束,只是暂时冻结)的时候无法调用该方法 32 - (void)applicationWillTerminate:(UIApplication *)application { 33 NSLog(@"WillTerminate"); 34 } 35 // 应用程序接收到内存警告的时候就会调用,一般在该方法中释放掉不需要的内存(大部分是图片缓存) 36 - (void)applicationDidReceiveMemoryWarning:(UIApplication *)application 37 { 38 NSLog(@"DidReceiveMemoryWarning"); 39 } 40 @end
打开App时候调用
2016-04-29 18:13:10.814 4.29UIApplication Delegate[12099:1953043] didFinishLaunchingWithOptions 2016-04-29 18:13:10.835 4.29UIApplication Delegate[12099:1953043] DidBecomeActive
App进入后来的时候调用
2016-04-29 18:15:11.888 4.29UIApplication Delegate[12099:1953043] WillResignActive
2016-04-29 18:15:12.457 4.29UIApplication Delegate[12099:1953043] DidEnterBackground
重新进入App时候调用
2016-04-29 18:15:54.764 4.29UIApplication Delegate[12099:1953043] WillEnterForeground
2016-04-29 18:15:55.281 4.29UIApplication Delegate[12099:1953043] DidBecomeActive
二、UIApplicationMain
1、启动原理
程序打开后会先进入main函数,执行UIApplicationMain函数
代码如下:(在main.m中)
#import <UIKit/UIKit.h> #import "AppDelegate.h" int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); // // argc: 系统或者用户传入的参数个数 // argv: 系统或者用户传入的实际参数 // 1.根据传入的第三个参数创建UIApplication对象 // 2.根据传入的第四个产生创建UIApplication对象的代理 // 3.设置刚刚创建出来的代理对象为UIApplication的代理 // 4.开启一个事件循环 } }
即
2、UIApplicationMain的底层实现:
(1)根据principalClassName提供类名,创建UIApplication对象
(2)创建UIApplicationDelegate对象,并且成为UIApplication对象代理,app.delegate = delegate
(3)开启一个主运行循环,处理事件,可以让程序保持运行
(4)加载info.plist,并且判断有没有指定main.storyboard,如果指定,就会去加载
3、程序启动的完整过程:
(1)执行main函数
(2)执行UIApplicationMain 函数
创建UIApplication对象
创建UIApplication的delegate对象
(3)根据Info.plist获得最主要storyboard的文件名,加载最主要的storyboard(有storyboard)
创建UIWindow
创建和设置UIWindow的rootViewController
显示窗口
(3)delegate对象开始处理(监听)系统事件(没有storyboard)
程序启动完毕的时候, 就会调用代理的didFinishLaunchingWithOptions方法
需要手动在didFinishLaunchingWithOptions创建UIWindow
创建和设置UIWindow的rootViewController
显示窗口
代码如下(在AppDelegate.m中):
1 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 2 //创建窗口 3 self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 4 //加载storyBoard,后面的Main首字母是大写的!! 5 //nil当作为参数的时候表示NSBundle mainBundle 6 UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; 7 //通过storyBoard创建一个控制器 8 UIViewController *viewController = [storyBoard instantiateInitialViewController]; 9 self.window.rootViewController = viewController; 10 //显示窗口 11 [self.window makeKeyAndVisible]; 12 return YES; 13 }
注:手动创建storyBoard之前注意要删除Main