app life cycle


通常 app 都是通过自己的代码和系统框架之前巧妙地合作才能够正常运转的.系统框架提供了基础架构来满足 app 的正常运转.然后 app 本身提供代码来满足个性化在这个框架基础之上.为了能够很好地理解这之间的奥妙就需要理解 iOS 基础架构以它们是怎么运作的.

iOS 框架已依赖于 MVC 的设计模式的.理解这个模式是很关键的一步,同样也能够帮助熟悉 O-c 这样的语言.如果是新人报道,推荐阅读 *Start Developing iOS Apps Today*来熟悉.

###主方法

大家可能都知道,基于 c 的程序它们都是通过一个` main` 函数作为整个程序的入口的. iOS 也如法炮制. 唯有不同的是你不需要自己写这个 main 函数.` xcode` 会帮助创建在你新建项目的时候. 一般情况下你是不需要去修改它的.

```
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
 
int main(int argc, char * argv[])
{
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}
```

这里唯一需要指出的就是`main` 函数它的职责就是负责管理` UIKit framework` 然后` UIApplicationMain` 函数会负责这个进程,然后创建 app 的主要对象. 从` storyboard` 那里加载 app 的 UI.然后加载app 代码里那些需要初始化的工作. 然后就是开始 app 的` run loop` 节奏了.这个步骤中唯一需要处理的就是提供` storyboard` 文件还有个性初始化的代码.

###app 的结构

在 app 启动的时候,` UIApplicationMain` 函数会负责承建一系列比较关键的对象然后让这个 app 跑起来.对于每一个 app 来说关键的关键就是这个` UIApplication` 对象.它的作用就是负责处理 app 里的对象和系统之间的交互.下图会简要描述它们之间的关系.

![Key objects in iOS app](https://qiita-image-store.s3.amazonaws.com/0/56713/fe6c9ed1-e09a-0452-cae3-e2d6288fc6e0.png "Key objects in iOS app")


上图中需要说明的 iOSapp 使用的 MVC 架构,这个架构会吧 app 的数据和业务逻辑从视图中抽取出来.这个架构师非常重要的一个概念,它能够让 app 跑在不用的终端或者不同的屏幕尺寸上.

下面来看看详细的这些对象它们的定义和作用:

|对象|描述|
|---|---|
|UIApplication|这个` UIApplication`主要管理事件,还有一个高阶的 app 行为,同时它还**汇报** app 的过渡和一些特殊的事件(如进来的消息推送)给程序的` delegte`, 它是自定义一个对象.|
|App delegate|这个类是代码自定义的核心,它和` UIApplication`一起协作完成 app 的初始化,状态过渡,高级别事件响应.这个类也是保证在每一个 app 中会有,所以它经常用来处理 app 数据的初始化.|
|Documents and date model 对象|数据模型对象就是用来存储 app 内容的,那些属于你 app 的内容.例如一个银行的 app 需要存储交易信息,一个绘画用的 app 需要存储下如何绘制一幅画的所有步骤等. app 同样也可以使用` document 对象`(` UIDocument` 的自定义子类)来管理 app 所有的数据对象. Document 对象不是必须的,但是提供了一个非常方便的方法来组织数据到一个单独的文件.|
|View 控制器对象|视图控制器对象管理 app 内容如何呈现.一个视图控制器能够控制一个单独的视图和很多子视图. 呈现的时候视图控制器会把这些视图安装到 window 中让这个视图可见. 这个` UIViewController` 是所有试图控制器的父类,他提供了基础类用来加载和显示视图. 还有如旋转终端做出旋转响应等. `UIKit` 和其他的框架定义了另外的试图控制器类,他们实现了标准的系统接口,如 image picker,tab bar, 导航等接口.|
|UIWindow 对象|一个` UIWindow` 对象统筹了一个或者多个视图展现到屏幕上.大部分的 app 都只有一个 window, 但是也有 app 有其他的窗口用来展示内容, 用来做扩展的显示. 为了改变 app 的内容,需要使用视图控制器来修改展示内容的窗口,不能够想办法去替换这个 window. 除了展示视图外,它还可以和` UIApplication`协作来传递一些事件给视图和试图控制器.|
|视图对象|`视图和控制器`提供了一个视图展现形式给你的 app 的内容,一个视图就是用来渲染内容到指定的区域然后响应特定的事件. 控制器是一个特定的视图,用来实现类型的接口对象如按钮,文本框, toggle开关等. `UIKit` 框架提供了标准的视图用来很多不同的类型的内容. 你也可以定义自定义的视图, 通过继承` UIView` 来实现. app 除了和视图控制器还有` Core Animation layer``Later对象`其实就是数据对象,用来展示内容.|


两个 iOSapp 之间的区别就是它的数据是如何管理的然后内容是如何展示给用户的.基本上你的 app 不会取决于合 UIKit 对象之间的交互,它只会帮助定义用户的行为. 它的作用举例说就是当一个方法委托你改变 app 的状态,然后你的自定义代码做出相应的动作回应.


###主运行循环

所谓`主运行循环`就是指所有和用户有关的事件.` UIApplication`对象会在 app 启动的时候设置这个 loop.然后用来处理事件和负责更新视图相关的接口.正如名字提示的那样, 这个`主运行` loop 它是跑在 app 主进程里的.这个就保证了用户相关的事件抗议被有序的处理.

下图说明了这个架构,然后用户事件是如何被处理的.用户和终端的交互,会产生很多事件,然后系统 会利用由` UIKit` 创建的特定端口来把这些事件分发到 app, 事件是由队列形式在内部由 app 一个个的分配打牌`主运行`的 loop 机制里被处理.这个` UIApplicaiton` 是第一个收到事件的,然后做决定需要什么样子的处理.一个` touch` 的事件会被分发给主窗口对象,接着它会被分给具体的视图,就是那个接受` touch` 的视图,其他的事件可能就通过不同的路径到了 app 里不同的对象里.

![Kobito.kex0VC.png](https://qiita-image-store.s3.amazonaws.com/0/56713/02684337-4d81-cf2e-c7f4-6db48ac9b0c3.png "Kobito.kex0VC.png")

很多类型的事件都是能够在 iOS app 中处理的,很多常见的事件会在下方例举. 下表中的很多事件都是通过`主运行`事件循环机制来回处理的.但是也会有例外.一些事件在被送到那里之后会发到一些委托对象( delegate object) 或者发送给一些由你自己提供的块.

####常见事件

|事件类型|接受事件|注意|
|-------|-----|---|
|Touch|那个发生事件的视图|视图就是负责人,任何不能够被处理的事件会被转发给负责人链的下级去处理|
|Remote control shake motion event|第一个负责对象||
|Accelerometer Magnetometer Gyroscope|你指定的对象||
|Location|指定的对象||
|Redraw|需要更新的视图||


一些事件如 touch 或者 remote control 的事件他们都是由 app 的` responder 对象`来处理的,响应对象在你的 app 中无处不在. (如 UIApplication, 视图对象, 视图控制器等等.)

###app 的执行状态

|State|Description|
|------|-----------|
|Not running|app 没在跑而且被系统 kill掉了|
|Inactive|系统在前台跑着呢但是没有收到任何的事件|
|Active|系统在前台跑着而且有连续的事件进来这就是 app 在前台执行的正常状态|
|Background|app 在后台执行|
|Suspended|app 在后台执行并且没有在之前代码,系统会在不通知的情况下自动把 app 移到这种状态,当挂起的时候, app 会保留在内存里面, 如果遇到低内存的情况,系统会在不通知的情况下 kill 掉这些挂起的app|


![Kobito.VWNgd2.png](https://qiita-image-store.s3.amazonaws.com/0/56713/47d187f1-aafc-a5ed-fff7-c4529d3215bd.png "Kobito.VWNgd2.png")

###终止 app

###多线程和并行
系统会给 app 创建主线程, 然后你可以创建其他的线程.对于 iOS app 来说,推荐的技术就是使用` Grand Central Dsipath(GCD)`,还有操作对象,其他的异步技术编程接口而不是自己去手动创建线程然后管理他们.例如 GCD 会让你定义你需要做的 work 然后他会负责调度他们.当你想要实现多线程或者并发的时候考虑小面的几个问题:

- 如果一个操作包括了试图,动画其他其他的 UIKit 类时,最好让 app 的主线程去处理.
- 长时间跑的任务最好让后台线程去处理.
- 在启动的时候尽可能把任务从主线程上拿走.

参考 [Concurrency Programming Guide](https://developer.apple.com/library/ios/documentation/General/Conceptual/ConcurrencyProgrammingGuide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40008091)


ref:https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/TheAppLifeCycle/TheAppLifeCycle.html