1、App生命周期

IOS架构是由许多设计模式实现,如model-view-controller 和 delegation模式。

1.1 main函数

与其它框架类似,IOS框架的入口也是从main函数,但是无需程序猿去实现这个main函数,Xcode已经帮我们实现了,在main函数中启动UI框架,其实它是调用了UIApplicationMain函数。

main函数在项目的Supporting Files/main.m文件中:

1 #import <UIKit/UIKit.h>
2 #import "AppDelegate.h"
3 int main(int argc, char * argv[])
4 {
5     @autoreleasepool {
6         return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
7     }
8 }

当执行UIApplicationMain函数后,IOS会自动执行如下的操作:

1) 首先,根据传递给UIApplicationMain函数的类名,IOS创建了一个app delegate对象。

2) 接着,创建一个新的UIWindow对象,并将其赋值给main screen。

3) 如果用户定义了app delegate有实现一个window属性,那么将上述新创建的UIWindow对象赋给window属性。

4) 根据app的属性列表文件(property list file)提供的信息,加载main storyboard文件。

5) 然后,实例化main storyboard文件中的起始view controller(initial view controller)。

6) 将window对象的rootViewController属性设置为上述新创建的起始view controller对象。

7) 进而,IOS将调用app delegate对象的application:didFinishLaunchingWithOptions:方法。

8) 最后,IOS调用window对象的makeKeyAndVisible方法将window对象显示在屏幕中。

当在4)中,若不能识别main storyboard文件时,UIApplicationMain函数将不在执行后续步骤,转而执行app delegate对象的如下方法。用户可以实现类似的内容:

 1 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
 2 {
 3     self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
 4     UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MyStoryboard" bundle:nil];
 5     MainViewController *mainViewController = [storyboard instantiateInitialViewController];
 6     self.window.rootViewController = mainViewController;
 7     // code to configure the view controller would go here
 8     [self.window makeKeyAndVisible];
 9     return YES;
10 }

1.2 app架构

在main中调用了UIApplicationMain函数,在该函数设置了一些关键对象而且启动的app。而这些关键对象的中心是UIApplication对象,它的工作是促进用户与系统中的其它对象进行交互,如图 11所示。

图 11 IOS架构的关键对象

IOS架构采用mvc模式组织系统中的对象,它将app的数据、业务逻辑与可视化组建分开,从而实现松耦合的关系。

1.3 main Run Loop

在UIApplication对象中设置了 run loop,它不断了接收设备产生的事件,从而将事件传递给了事件响应者,如图 12所示。

图 12 main run loop事件处理

1.4 运行状态

IOS app其实就是UIApplication对象,该对象在生命周期的任何时刻都存在如表 11的状态,其中各个状态之间还存在如图 13所示的状态变化图,当app发生状态变化时会调用UIApplicationDelegate协议的某个方法,具体方法可参考帮助文档。

表 11 app状态

状态

描述

Not Runing(非运行)

应用没有运行,或者是正在运行但被系统终止

Inactive(前台非活动)

应用正在前台运行但当前没有接收到事件(可能在执行其它代码)

Active(前台活动)

应用正在前台运行并且能接受到事件,这是正常的前台状态

Background(后台)

应用进入后台后,依然能够执行代码。如果有可执行的代码,就会执行代码;如果没有可执行的代码或者将可执行的代码执行完毕,应用会马上进入挂起状态。

Suspended(挂起)

处于挂起的应用进入一种"冷冻"状态,不能执行任何代码。如果系统内存不够,应用会被终止。

图 13 IOS app状态变化图

2、后台执行

当用户不使用app时,那么系统将app转换为后台执行(background)。但一般情况下,app只是在background状态做短暂的停留,随即会马上进入挂起状态(suspended)。当然也可以延长在挂起状态的时间。

2.1 有限执行任务

进入background的app将很快进入suspended。如果需要app进入background后增加一些额外的时间来完成任务,那么可以调用如下两个UIApplication对象的方法来向系统申请,让app不立即进入suspended状态:

1 -(UIBackgroundTaskIdentifier)beginBackgroundTaskWithName:(NSString*)taskName
 expirationHandler:(void (^)(void))handler
2 -(UIBackgroundTaskIdentifier)beginBackgroundTaskWithExpirationHandler:(void(^)(void))handler

调用这两个方法之一能够执行申请一些额外的时间来完成任务,但在任务完成后,需要调用endBackgroundTask: 方法来通知系统任务已经完成,从而系统可以挂起该app。

如下的例子展示了app在进入后台时,创建一个长时间运行的任务。在这个例子中,将任务提交到异步的dispatch queue中去执行,这么做是为了applicationDidEnterBackground方法能够及时返回,防止主线程发生阻塞。

 1 - (void)applicationDidEnterBackground:(UIApplication *)application 
 2 {
 3      _bgTask = [application beginBackgroundTaskWithName:@"MyTask" expirationHandler:^{
 4         [application endBackgroundTask:_bgTask];
 5         _bgTask = UIBackgroundTaskInvalid;
 6     }];
 7     
 8     // Start the long-running task and return immediately.
 9     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
10     // Do the work associated with the task, preferably in chunks.
11         NSLog(@"hello world");
12         [application endBackgroundTask:_bgTask];
13         _bgTask = UIBackgroundTaskInvalid;
14     });
15 }

2.2 后台下载任务

为了支持app在后台继续下载,应该使用NSURLSession对象进行下载。当使用NSURLSession配置后台下载任务时,系统将创建独立的进程来控制这些下载任务,从而如果app被挂起或结束,那么系统将在后台继续下载这些任务,并且当任务下载完成后,可以重新调起app。

关于如何配置和创建NSURLSession对象,可以参考另一篇文章《iOS 网络编程:session》。一旦配置完NSURLSession对象后,任务的下载或上传的控制权将转移给的系统,从而:

1) 如果任务已经完成,并且app仍处于运行状态(前台或后台),那么session对象将通知delegate;

2) 如果任务还没完成,并且app已经被系统结束,那么系统将持续在后台管理下载任务;

3) 如果任务还没完成,并且app被用户终止了,那么系统将取消下载任务。

2.3 实现长时任务

2.3.1 后台执行任务类型

对于需要长时间执行的任务,必须通过系统的许可才能在后台执行(不会被挂起)。在IOS中只有如下的几种类型才允许长时间在后台执行:

1) app在后台执行一些用户听得见的内容,如音乐播放器;

2) app在后台路径内容;

3) app持续获取用户的位置信息,如导航app;

4) app支持Voice over Internet Protocol (VoIP),VoIP是一种协议。

5) app需要频繁处理下载内容;

6) app频繁接受外部设备的信息。

2.3.2 声明app后台类型

若需要app能在后台运行,必须在项目的Info.plist文件中进行声明。即在文件中的"Required background modes"中添加一项app支持的后台类型,如图 21所示。

图 21 声明app后台支持类型

3、app状态转换策略

app有很多状态,而且当状态发生变化时将会通知app对象,即通知app delegate协议。从而可以在app delegate方法中监听app的状态变化,从而做出合适的响应。

3.1 启动时间

在app启动时,系统将自动加载主storyboard文件和初始view controller。其中app的启动时间是从调用delegate的application:willFinishLaunchingWithOptions: 方法开始到application:didFinishLaunchingWithOptions:方法调用结束这段时间,系统将尽可能的减少app的启动时间,所以app启动的时间将控制在5s内。如果在这5s内app没有完成启动,那么系统将不负责任的结束它。所以对于需要初始化的内容应该放在第二线程进行,从而提供启动的时间性能。

3.1.1 启动周期

当app被启动时,它将从 not running状态转变为active状态或者是background状态。简单地说,在app启动时,系统将创建一个进程来运行main函数,然后该main函数再调用了UIApplicationMain函数来初始化UI界面。

        1) not running状态转换为active状态

如图 31所示,展示了app从开始启动到进入前台active状态的过程,包括调用的app Delegate方法的细节。

图 31 启动app进入foreground状态

       2) not running状态转换为background状态

app也有可能在启动后直接进入后台状态,如图 32展示的就是app从启动到进入后台的过程。过程与进入前台类似,只是后半段不同。注意的是后台转换过程也是会加载用户的interface文件,只是没有在窗口中显示。

图 32 启动app进入background状态

3.1.2 横屏模式启动

app有两种显示模式:Landscape(横屏)和portrait(竖屏),默认是portrait模式。目前有两种方式来设置显示的方式:

        1) 界面设计

界面显示非常简单,只需在项目的设置中指定支持的方向即可,如图 33所示。

图 33 显示模式设置

         2) 代码设计

代码方式是通过在view controller类中重载supportedInterfaceOrientations方法,返回想要显示的方向,如下所示。

1 -(UIInterfaceOrientationMask)supportedInterfaceOrientations
2 {
3     return UIInterfaceOrientationMaskLandscapeLeft;
4 }

3.2 短暂中断

Alert-based中断将导致app的控制权丢失,但app仍然在前台执行,只是不能接收来自系统的触摸事件(能够接收其它类型的事件)。比如一个来电中断发生了,那么app将转换为inactive状态,app将一直保持这个状态,直到中断结束。

如图 34所示,当一个事件发生时,用户的处理过程,如果用户不忽略这个中断,那么app将进入inactive状态,同时跳入其它app中。

图 34 alert-based中断的处理过程

3.3 进入前台

当app返回到前台时,应该重新启动那些进入后台被暂停的任务,其状态变化如图 35所示。

图 35 从后台转入前台的状态变化

3.4 进入后台

当用户按了Home按钮、按了Sleep/Wake按钮,或是系统系统了另外的app,那么当起的app将从前台状态进入后台状态,如图 36所示。在applicationDidEnterBackground:方法返回后,大多数app将快速进入suspended 状态,当然若需要额外的时间在后台状态执行,那么也可以继续执行。

图 36 从前台进入后台的状态变化

在进入后台状态后若发生了一些view内容的变化,可以调用snapshotViewAfterScreenUpdates: 方法手动更新主view的内容。当然在后台状态返回后,即进入前台后,app也会自动更新发生变化的内容。

4、参考文献

[1] App programming guide for IOS.

iOS UIKit:App的更多相关文章

  1. iOS UIKit:viewController之动画(5)

    当弹出一个view controller时,UIKit提供了一些标准转换动画,并且也支持用户自定义的动画效果. 1 UIView动画 UIView是自带动画实现功能,其中有两种方式实现:        ...

  2. iOS UIKit:viewController之定义(2)

    @import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...

  3. iOS UIKit:viewController之层次结构(1)

    ViewController是iOS应用程序中重要的部分,是应用程序数据和视图之间的重要桥梁.且应用程序至少有一个view controller.每个view controller对象都负责和管理一个 ...

  4. iOS UIKit:view

    @import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css); @import url(/ ...

  5. iOS UIKit:TableView之单元格配置(2)

    Table View是UITableView类的实例对象,其是使用节(section)来描述信息的一种滚动列表.但与普通的表格不同,tableView只有一行,且只能在垂直方向进行滚动.tableVi ...

  6. iOS UIKit:TableView之表格创建(1)

    Table View是UITableView类的实例对象,其是使用节(section)来描述信息的一种滚动列表.但与普通的表格不同,tableView只有一行,且只能在垂直方向进行滚动.tableVi ...

  7. iOS UIKit:CollectionView之设计 (1)

    collection view(UICollectionView对象)使用灵活和可扩展的布局来描述有序的数据项,其一般情况下以网格的形式来展示内容,但并非一定如此. 1 基础 为了将数据展示在屏幕中, ...

  8. iOS UIKit:Navigation Controllers

    navigation controller是一种层次结构的container view controller,即其通过一个view controllers栈来管理内部的content view con ...

  9. iOS UIKit:viewController之Segues (4)

    @import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...

随机推荐

  1. Maven镜像配置

    镜像是为了提供更快的服务 如图:X就认为是Y的一个镜像. 编辑settings.xml配置中央仓库镜像: <settings> ... <mirrors> <mirror ...

  2. bzoj 2818: Gcd 歐拉函數

    2818: Gcd Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1633  Solved: 724[Submit][Status] Descript ...

  3. 3d max export for unity3d

    3d max export for unity3d @by 广州小龙 1.单位问题 建模的时候,设置unity的Units Setup的单位是Meters,导出FBX文件的时候,单位为厘米(Centi ...

  4. 【HDU3440】House Man (差分约束)

    题目: Description In Fuzhou, there is a crazy super man. He can’t fly, but he could jump from housetop ...

  5. HTTP 状态代码

    转自:https://support.google.com/webmasters/answer/40132 HTTP 状态代码 如果向您的服务器发出了某项请求要求显示您网站上的某个网页(例如,当用户通 ...

  6. win7中的Uac与开机自动启动(好几种办法,特别是用不带UAC的程序启动UAC程序是一个简单的好办法,写驱动自启动更是了不得)

    在另一篇文章中已经介绍了给Exe加上Uac的方法,在使用的过程中我们会发现,如果把带Uac的Exe写入注册表的Run中,是无法实现开机自动启动的,原因就是带Uac的exe需要申请管理员权限,以便运行执 ...

  7. SQL*Net more data from client

    SQL*Net more data from client The server is waiting on the client to send more data to its client sh ...

  8. :: error: 无法打开文件“d:\Qt\2010.05\qt\lib\qtmaind.lib”

    新建一个工程马上编译也会出现这个错误:: error: 无法打开文件“d:\Qt\2010.05\qt\lib\qtmaind.lib” vc的编译器, 而你安装的是mingw版本的qt. 工具-选项 ...

  9. MVC5 学习整理

    一.概述 MVC简介: •       模型(Model) “数据模型”(Model)用于封装与应用程序的业务逻辑相关的数据以及对数据的处理方法.“模型”有对数据直接访问的权力,例如对数据库的访问.“ ...

  10. if语句,if...else if语句和switch...case语句的区别和分析

    前段时间在工作中遇到了一个关于条件判断语句的问题,在if语句,if else if语句和switch case语句这三者之间分析,使用其中最有效率的一种方法. 所以就将这个问题作为自己第一篇博客的主要 ...