App 的生命周期

原文翻译: The App Life Cycle

App 可以智能地将你自定义的代码和系统框架相结合的。系统的框架提供基本的方法,这些方法是app可以运行的基础,而你提供的代码则需要展示基础框架提供给app的外表和你想要的app的样子。这篇文章有助于你了解一些iOS的基础框架以及其如何工作。
iOS frameworks 依赖于MVC及代理的设计模式。理解这些设计模式对于成功创造一款app是至关重要的。这也有助于帮助你了解OC语言及其特点。

The Main Function

C语言的app 和iOS app程序的进入点是不同的。他们的不同点在于,iOS app 你不需要自己写main function。Xcode 创建了这段函数,作为你工程的基础。Listing 2-1 展示给你这段功能代码。不出意外,你不应该改变这段main Function 的实现。
这里写图片描述
UIApplicationMain方法通过创建app的核心来掌握这一过程,过程包括从storyboard文件加载app的用户界面,调用你用来初始化的自定义代码,并且将app 的runloop 运转起来。你唯一需要提供的就是storyBoard和自定义的初始化代码。

App 的结构

经过启动后,UIApplicationMain 函数建立起了一些主要对象并且使app运行起来。每个app的核心都是 UIApplication 对象,它的职责是使系统和app的其他对象进行交互。请看Figure 2-1 。首先注意的是iOS app 用的是mvc 结构。这一结构使app的数据和业务逻辑分离。这一结构对于app可以在不同屏幕大小的手机上无差异化运行至关重要。
这里写图片描述

iOS App中各个对象的角色
UIApplication object其掌握eventloop 和其他高级别的app行为。它也把app的切换和一些特殊的事情(像收到推送通知)报告给它的代理Application Delegate ,在代理中可以自定义一些代码
App delegate object它是你自定义代码的核心。它与UIApplication 合作去处理app 的初始化,app运行状态改变和很多高级别的app 事件。App delegate 是唯一的在每个app中一定都会出现的对象,所以它经常会用来建立app初始数据结构。
Documents and data model objects数据模型储藏了你app的内容,并且是针对你的app的。举例来说,一个银行的app可能会储藏一个包含金融交易的数据库,一个绘画app则会储藏图片数据或则一系列可以创建图片的绘画指令。App 也可以用document对象 (一般就是UIDocument)去管理他们的数据模型。Document 对象需要提供一个便捷的方式去将数据归档。更多的document信息,请参阅Document-Based App Programming Guide for iOS
View controller objects它管理者你的app再屏幕上显示的内容。一个ViewController 管理者一个View和这个View 的子控件。当被展示时,控制器通过将它的views添加在app的window上,让它的views可视化。 UIViewController 类是所有viewcontroller 的基类。它提供了默认的方法去加载views,展现views,基于设备旋转产生的视图旋转,以及一些标准系统的行为。UIKit 和其他frameWork 定义了很多种类的 控制器种类去实现标准系统界面,比如说图片选择器,底部选择条界面和导航界面等。更过控制器信息,请参阅View Controller Programming Guide for iOS.
UIWindow object他协调一个或多个view 在屏幕上的展示。很多app 只有一个window,这个window将内容展示在主界面上,但是app是可能有其他的window来展示其他的对外展示的一些内容。
View objects, control objects, and layer objectViews 和controls为你的app内容提供了一个可视化的展示。View 是用来在指定长方形区域绘画,并且在指定区域内对事件做出反应的一个对象。Controls 和buttons ,textFeild,和switch 开关相似。 UIKit framework 提供了标准的视图去呈现不同种类的内容。你可以通过继承的方式自定义你的视图。 除了加入views和controls ,app 也可以把把核心动画的图层加入到view上,或者是control 上。layer 实际上是数据对象,它代表了可视化内容。views 在幕后频繁的使用layer来渲染他们的内容。你也可以把自定义的layer加载你的界面上,来实现复杂的动画和其他复杂的视觉效果。

两个app的区别源自于它们处理数据和展示数据的方式不同。很多UIkit的交互并不是定义了你的app,而是规范了app的行为。举个栗子,app delegate 让你知道了何时你的app改变了状态,所以你可以用自定义的代码对每个时刻做出合适的反应

The Main Run Loop

一个app的main Run Loop 处理这所有用户相关的事件。在程序启动的时刻,UIApplication 建立了main run loop 并且用它来处理基于view的界面的刷新和一些事件。Main Run Loop在主线程上。这保障了用户相关事件在他们被接收到的线程中按顺序的被处理。

Figure 2-2 展示了main runloop的结构及用户事件引起的app的反应。当用户和一个设备进行交互时,与那些交互有关的事件通过系统产生并通过特殊的port(port通过UIKit创建)传递给app。App将事件按顺序排队并且一个接一个将他们分配给main runloop 来执行。UIApplication 是第一个接收到时间的对象并且决定需要如何处理。一个触摸事件通常会分配给main Window 上,main Window将按顺序把事件分配给发生触摸事件的view上。其他事件会通过不同的app 对象有略微不同的路径。
这里写图片描述
很多事件可以在iOS App中传递。一般形式如Table 2-2.很多这类事件在main runloop中处理,但是也有一些例外。一些事件被指派到了代理或是你提供的block中。如果想了解如何处理多种事件类型,请参阅Event Handling Guide for UIKit Apps.

Table 2-2 普通iOS app的事件
事件类型传递给。。。备注
Touch事件发生的viewView是响应者。任何触摸事件如果没有被view处理将沿着响应链乡下传递并进行处理。
远程控制、摇动事件第一响应者远程控制事件是用来控制媒体播放装置的,来自于耳机或者其他配件。
加速器、磁力计、陀螺仪你指定的对象这些硬件相关的事件传递给你指定的对象
定位你指定的对象请参阅 Location and Maps Programming Guide
重绘需要更新的view重绘事件不需要一个事件,仅仅只是调用的view去重绘自己。请参阅 Drawing and Printing Guide for iOS.

一些事件,例如触摸和远程事件,通过app的响应者处理。响应者在你app里无处不在(包括UIApplication 、View、ViewController等)。大部分事件会找到一个明确的响应者,但是如果需要其他的响应者处理事件,事件可以沿着响应链乡下传递。例如一个view不处理事件可以把事件传递给它的父视图或者是控制器。
触摸事件发生在controls中(例如button)处理的机制是跟发生在其他view的触摸事件是不同的。controls只有有限的几种典型的交互方式,所以那几种交互被重新包装成了action消息并且传递给给合适的目标。Target-action 设计模式使使用control 去出触发自定义的执行方式变得简便。

App的运行状态

在任何时刻,你的app一定是处于Table 2-3 的任一状态中。系统使你的app从一个状态进入另一个状态去配合系统事件的发生。例如当使用者按home键,一个电话打进来,或者其他中断app的事件发生,当前运行的app将改变它的状态。 Figure2-3 展示了app各个状态切换的路径。

状态描述
Not running不运行App没有启动,或者曾经运行过,但被系统杀死
Inactive不活跃App在前台运行但是此时却收不到事件。(尽管它可能在执行其他的代码。)app 通常仅仅在过渡到另一个不同状态时才会有inactive状态。
ActiveApp在前台运行并且接收事件。这是前台app的普通模式
BackgroundApp在后台并且执行代码。大部分app进入到这个状态时,马上要被挂起 suspended.然而一个需要额外运行事件的app可以保持在这一状态一定的时间。另外,一个app直接在 background 状态启动时,不会进入inactive状态而是直接进入background状态。跟多信息请参阅 Background Execution.
SuspendedApp在后台但是不执行代码。系统将自动的使app 进入这一状态,并且是在用户不知情的情况下。当被挂起,app保留了内存但是不执行任何代码。当低内存情况发生,系统将清除挂起的app为前台app留出足够大的内存。

这里写图片描述
状态的切换伴随着调用响应的app delegate方法。这些方法可以配合你进行一些状态切换的处理。

  • application:willFinishLaunchingWithOptions:—这个方法给你在app启动时执行代码的机会
  • application:didFinishLaunchingWithOptions:— 在app启动后,展现给用户之前,这个方法允许你进行最后的初始化设置
  • applicationDidBecomeActive:—让你的app知道,它将变为前台app 。使用这个方法用来做最后一分钟的准备工作
  • applicationWillResignActive:—你的app将不再是前台app了,用这个方法让你的app进入一个静止状态
  • applicationDidEnterBackground:— app在后台活动,app随时会被挂起
  • applicationWillEnterForeground:— app将要从后台运行进入到前台运行,但app并不是一个活跃的app
  • applicationWillTerminate:—你的app将被杀死,当你的程序被挂起了,这个方法不会被调起。

App的终止

App 必须为随时会发生的终止做好准备,并且无法等到储存用户数据后或者实现重要的任务后再停止程序。系统自发的终止时app 生命周期的一部分。系统通常终止app去释放内存并且为用户运行的其他程序的运行准备内存空间,系统也有可能是因为错误的操作或者是因为不能及时响应某些事件而导致系统终止。
当被挂起的app被杀死后,用户收不到通知,系统自动杀死程序并且释放相应的内存。如果app正在后台运行,并没有被挂起,系统在程序被杀死前调用applicationWillTerminate:方法。当系统重启的时候,系统不会调用这个方法。
除了系统结束你的app之外,用户也可以用多任务界面杀死app。用户导致的app终结的效果和被挂起的app被杀死的情况一样。App被杀死并且没有任何的通知发给这款app。

线程和并发

系统为你的app创建了主线程,你可以创建其他的线程去完成一些其他任务。对iOS app来说,最为推荐的是GCD而不是自己创建并管理线程。GCD让你定义你在线程中想要做的任务,但是系统决定如何最优的运用cpu。让系统处理线程管理简化了你的代码,增强了你的代码的正确性。

当你自己处理线程和并发时,要考虑到以下几点:

-

  • 当处理视图、核心动画及其他的UIKit类时通常只能在主线程中处理。也有一些特例,例如基于图片的操作通常可以在后台线程中进行,但如果出现任何不确定情况,还是要把主线程进行这类操作作为指导思想。
  • 长时间的任务小放在后台来进行。包括网络请求,文件存取,或者大量数据处理需要使用GCD或者其他线程方法。
  • 在启动时,尽量让任务在其他线程中进行。在启动时你的app时,要尽快搭建起用户使用界面。只有那些牵涉到建立用户使用该界面的任务才能在主线程中进行。其他所有任务应该异步进行,让用户尽快看到界面。

更多多线程内容请参阅 Concurrency Programming Guide

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值