iOS程序启动原理

要想说清楚 iOS 的程序启动原理,首先必须了解一个类叫 UIApplication,下面请看 UIApplication 的作用

UIApplication

UIApplication 对象是一个单例对象。

有很多作用:

打开网页、打电话

UIApplication 有个功能十分强大的 openURL: 方法

1
- (BOOL)openURL:(NSURL*)url;

openURL:方法的部分功能有

打电话

1
2
UIApplication *app = [UIApplication sharedApplication];
[app openURL:[NSURL URLWithString:@"tel://10086"]];

发短信

1
[app openURL:[NSURL URLWithString:@"sms://10086"]];

发邮件

1
[app openURL:[NSURL URLWithString:@"mailto://12345@qq.com"]];

打开一个网页资源

1
[app openURL:[NSURL URLWithString:@"http://ios.itcast.cn"]];

打开其他app程序…

隐藏状态栏

在iOS7以后,状态栏默认由控制器决定(但是控制器不能搞动画)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 隐藏状态栏
//- (BOOL)prefersStatusBarHidden
//{
// return YES;
//}

// 设置状态栏样式
//- (UIStatusBarStyle)preferredStatusBarStyle
//{
// 白色
// return UIStatusBarStyleLightContent;
//}

- (void)statusHidden
{
// 获取UIApplication
UIApplication *app = [UIApplication sharedApplication];


// 隐藏状态栏
// [app setStatusBarHidden:YES];

//
[app setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];
}

设置提醒数字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- (void)application
{
UIApplication *app = [UIApplication sharedApplication];

// 设置appIcon提醒数字,必须注册用户通知
app.applicationIconBadgeNumber = 10;

// iOS8 以后需要先注册用户通知

// 创建用户通知
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge categories:nil];
// 注册用户的通知
[app registerUserNotificationSettings:settings];

// 设置联网状态(菊花) 设置联网指示器的可见性
app.networkActivityIndicatorVisible = YES;

}

UIApplicationDelegate

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

// 学习代理方法,只需要知道这个什么时候调用,这个方法可以用来干嘛

// 程序启动完成的时候调用
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
NSLog(@"%s",__func__);
return YES;
}

// 当app失去焦点的时候调用
- (void)applicationWillResignActive:(UIApplication *)application {
NSLog(@"%s",__func__);
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}

// app进入后台的时候调用
// app忽然打断的时候,在这里保存一些需要用到的数据
- (void)applicationDidEnterBackground:(UIApplication *)application {
NSLog(@"%s",__func__);
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}


// app进入即将前台
- (void)applicationWillEnterForeground:(UIApplication *)application {
NSLog(@"%s",__func__);
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}

// 当app获取到焦点的时候调用,意味着app可以与用户交互
- (void)applicationDidBecomeActive:(UIApplication *)application {
NSLog(@"%s",__func__);
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}

// app被关闭的时候调用
- (void)applicationWillTerminate:(UIApplication *)application {
NSLog(@"%s",__func__);
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}


// app接收到内存警告的时候调用
// 清空图片的缓存
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application
{
NSLog(@"%s",__func__);
}

程序启动原理

在了解了 UIApplication 之后,就要深入 iOS 在程序启动初期到底做了些什么。

通过对 UIApplication 的了解,我们发现 UIApplication 其实是用来处理应用级别的事件的类型。

下图比较清晰的展示了 iOS 程序启动后执行代码的步骤

  1. 进入 main 函数,执行 UIApplicationMain

    • UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]))
      • 参数:
        • argc、argv:直接传递给 UIApplicationMain 进行相关处理即可

        • principalClassName:指定应用程序类名(app的象征),该类必须是 UIApplication (或子类)。如果为 nil ,则用UIApplication 类作为默认值

        • delegateClassName:指定应用程序的代理类,该类必须遵守 UIApplicationDelegate 协议

  2. UIApplicationMain 函数会根据 principalClassName 创建 UIApplication 对象,根据 delegateClassName 创建一个 delegate 对象,并将该 delegate 对象赋值给 UIApplication 对象中的 delegate 属性

  3. 接着会建立应用程序的 MainRunloop(事件循环),进行事件的处理(首先会在程序完毕后调用 delegate 对象的application:didFinishLaunchingWithOptions:方法),确保程序一直在运行,了解什么是 RunLoop运行循环

  4. 加载 info.plist 如果 info.plist 中指定 main 就会加载 main 所以我们才能看见 mian.storyboard 的界面,加载完后,程序启动完成

  5. 程序正常退出时 UIApplicationMain 函数才返回

applicationState 说明

开始运行:

1
2
3
4
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
// 注意,此处不会调用- (void)applicationWillEnterForeground:(UIApplication *)application,因为并没有从后台进入前台的过程
- (void)applicationDidBecomeActive:(UIApplication *)application

按home回到主界面:

1
2
- (void)applicationWillResignActive:(UIApplication *)application 
- (void)applicationDidEnterBackground:(UIApplication *)application

从home唤起应用:

1
2
- (void)applicationWillEnterForeground:(UIApplication *)application 
- (void)applicationDidBecomeActive:(UIApplication *)application

再次按home回到主界面:

1
2
- (void)applicationWillResignActive:(UIApplication *)application 
- (void)applicationDidEnterBackground:(UIApplication *)application

干掉应用:

1
- (void)applicationWillTerminate:(UIApplication *)application;

需要注意的两点:

  • [[UIApplication sharedApplication] openURL:… ]此方法会和“按home回到主界面”的效果一样。较特殊的是拨打电话的时候,应用内拨打电话首先会弹出一个提示框,这时 applicationWillResignActive,确定拨打之后,调用 applicationDidEnterBackground,拨打完成后会顺序执行applicationWillEnterForeground,applicationDidBecomeActive

  • 下拉通知面板和上拉设置面板,都只会回调 applicationWillResignActive 与 applicationDidBecomeActive。

总结一下就是只有进入过后台才能进入前台。看不见了才是进入后台。只要看得见都要激活

文章作者: Ammar
文章链接: http://lizhaoloveit.cn/2014/08/02/iOS%E7%A8%8B%E5%BA%8F%E5%90%AF%E5%8A%A8%E5%8E%9F%E7%90%86/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Ammar's Blog
打赏
  • 微信
  • 支付宝

评论