App的生命周期

作者: 微笑中的你 | 来源:发表于2018-04-24 23:31 被阅读0次

应用程序是您的自定义代码和系统框架之间复杂的相互作用。系统框架提供了所有应用程序都需要运行的基本基础设施,并且您提供了定制基础设施所需的代码,并提供了您想要的外观和感觉。为了有效地做到这一点,它有助于理解一些关于iOS基础设施及其工作原理的知识。

iOS框架依赖于设计模式,比如模型-视图-控制器和委托。理解这些设计模式对于成功创建一个应用程序至关重要,它也有助于熟悉Objective-C语言及其特性。如果你是iOS编程的新手,那么请阅读iOS应用程序(Swift)的开发,以介绍iOS应用和Objective-C语言。

The Main Function

每个基于c的应用程序的入口点是main function,iOS应用程序也没有什么不同。不同的是,对于iOS应用程序,你不需要自己编写主函数。相反,Xcode创建这个函数作为基本项目的一部分。list 2-1显示了这个函数的一个例子。除了少数例外,您不应该更改Xcode提供的主要功能的实现。

list 2-1

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

唯一值得一提的是,它的主要功能是将控制权交给UIKit框架。UIApplicationMain函数通过创建应用程序的核心对象来处理这个过程,从可用的故事板文件加载应用程序的用户界面,调用自定义代码,这样就有机会做一些初始设置,并将应用程序的运行循环进行移动。您必须提供的只有故事板文件和自定义初始化代码。

app的结构

在启动过程中,UIApplicationMain函数设置几个关键对象并启动应用程序运行。每个iOS应用程序的核心都是UIApplication对象,其工作是促进系统和应用程序中的其他对象之间的交互。图2-1显示了大多数应用程序中常见的对象,表2-1列出了这些对象所扮演的角色。首先要注意的是,iOS应用程序使用的是模型-视图-控制器架构。该模式将应用程序的数据和业务逻辑与该数据的可视化表示分离开来。这种架构对于创建能够在不同屏幕大小的不同设备上运行的应用程序至关重要。

图2-1

表 2-1

Object Description
UIApplication UIApplication对象管理事件循环和其他高级应用程序行为。它还报告了关键的应用程序转换和一些特殊事件(比如传入推送通知)到它的委托,这是您定义的自定义对象。使用UIApplication对象,即,没有子类化。
App delegate 应用程序委托是定制代码的核心。该对象与UIApplication对象一起工作,以处理应用程序初始化、状态转换和许多高级应用程序事件。这个对象也是每个应用程序中唯一保证存在的,因此它经常被用来设置应用程序的初始数据结构。
Documents and data model 数据模型对象存储你的应用程序的内容,并且是特定于你的应用程序的。例如,一个银行应用程序可能会存储一个包含金融交易的数据库,而一个绘画应用程序可能会存储一个图像对象,或者甚至是绘制命令的序列,从而导致该图像的创建。(在后一种情况下,图像对象仍然是一个数据对象,因为它只是图像数据的一个容器。)
应用程序还可以使用文档对象(UIDocument的自定义子类)来管理一些或全部数据模型对象。文档对象不是必需的,但是提供了一种方便的方式来将属于单个文件或文件包的数据分组。有关文档的更多信息,请参见基于文档的iOS应用程序编程指南
View controller 视图控制器对象在屏幕上管理应用程序的内容。视图控制器管理一个视图和它的子视图集合。当呈现时,视图控制器通过在应用程序的窗口中安装它们来显示视图。
UIViewController类是所有视图控制器对象的基类。它提供了加载视图的默认功能,呈现它们,对设备旋转进行旋转,以及其他一些标准系统行为。UIKit和其他框架定义了额外的视图控制器类来实现标准的系统接口,如图像选择器、标签栏界面和导航界面。
有关如何使用视图控制器的详细信息,请参阅iOS的视图控制器编程指南
UIWindow 一个UIWindow对象在屏幕上协调一个或多个视图的表示。大多数应用程序只有一个窗口,在主屏幕上显示内容,但应用程序可能有一个额外的窗口,用于显示在外部显示上的内容。
要更改应用程序的内容,可以使用视图控制器来更改相应窗口中显示的视图。你永远不能代替window本身。
除了托管视图之外,windows还使用UIApplication对象将事件交付给视图和视图控制器。
view, control, layer 视图和控件提供了应用程序内容的可视化表示。视图是在指定的矩形区域中绘制内容并对该区域内的事件作出响应的对象。控件是一种专门的视图类型,负责实现常见的接口对象,如按钮、文本字段和切换开关。
UIKit框架提供了提供许多不同类型内容的标准视图。您还可以直接通过子类化UIView(或它的后代)来定义自己的自定义视图。
除了合并视图和控件之外,应用程序还可以将核心动画层合并到视图和控制层次结构中。层对象实际上是表示可视内容的数据对象。视图在后台密集地使用层对象来呈现它们的内容。您还可以向界面添加自定义层对象,以实现复杂的动画和其他复杂的视觉效果。

一个iOS应用程序与另一个应用程序的区别在于它管理的数据(以及相应的业务逻辑)以及它如何将数据呈现给用户。大多数与UIKit对象的交互没有定义你的应用程序,而是帮助你改进它的行为。例如,应用程序委托的方法可以让您知道应用程序何时改变状态,以便您的定制代码能够做出适当的响应。

主运行循环

应用程序的主运行循环处理所有与用户相关的事件。UIApplication对象在启动时设置主运行循环,并使用它处理事件和处理基于视图的接口的更新。顾名思义,主运行循环在应用程序的主线程上执行。这种行为确保了用户相关事件按接收顺序依次处理。

图2 - 2显示了主循环运行的体系结构以及用户事件导致应用程序采取行动。当用户与设备进行交互,这些交互相关事件由系统生成并交付给应用程序通过一个特殊的端口由UIKit设立。事件由应用程序在内部排队,并逐个发送到主运行循环执行。UIApplication对象是接收事件的第一个对象,并决定需要做什么。一个触摸事件通常被发送到主窗口对象,后者又将它发送到触摸发生的视图。其他事件可能会通过不同的应用程序对象略有不同的路径。

图2 - 2

许多类型的事件都可以在iOS应用程序中发布,最常见的在表2-2中列出。许多此类事件类型都是通过应用程序的主运行循环来实现的,但有些则不是。一些事件被发送到委托对象,或者传递给您提供的块。有关如何处理大多数类型的事件的信息——包括触摸、远程控制、运动、加速计和陀螺仪事件——参见iOS的事件处理指南。

事件类型 送到…… 备注
触摸 事件发生的视图对象。 视图是响应者对象。任何未按视图处理的触摸事件都被转发到responder chain进行处理。
远程控制和摇晃事件 第一响应者对象 远程控制事件是控制媒体播放和由耳机和其他配件产生的。
加速度计
磁强计
陀螺仪
您指定的对象 与加速度计,磁强计和陀螺仪硬件相关的事件被传送到你指定的对象。
位置 您指定的对象 您可以使用核心位置框架注册接收位置事件。有关使用核心位置的更多信息,请参阅位置和地图编程指南
重绘 需要更新的视图 重绘事件不涉及事件对象,而是简单地调用视图来绘制它自己。iOS的绘图架构描述在iOS的绘图和打印指南 中。

一些事件,比如触摸和远程控制事件,由应用程序的responder对象处理。Responder对象在你的app中无处不在(UIApplication对象,你的视图对象,你的视图控制器对象都是Responder对象的例子)。大多数事件针对特定的responder对象,但如果需要处理事件,则可以将其传递给其他响应器对象(通过responder chain)。例如,不处理事件的视图可以将事件传递给它的父视图或视图控制器。

在控件(例如按钮)中发生的触摸事件的处理方式不同于在许多其他类型的视图中发生的触摸事件。通常只有有限数量的交互可能具有控制,因此这些交互被重新打包成动作消息并交付给适当的目标对象。这个目标-动作设计模式使得使用控件在应用程序中触发自定义代码的执行变得容易。

app的执行状态

在任何时刻,你的应用程序都在表2-3中列出的状态之一。系统将您的应用程序从状态移动到状态,以响应整个系统中的操作。例如,当用户按下Home键时,会出现一个电话,或者其他任何中断发生,当前运行的应用程序会改变状态响应。图2-3显示了一个应用程序在从一个状态移动到另一个状态时所需要的路径。

表 2-3

State Description
Not running(没有运行) 该应用程序尚未启动或正在运行,但已被系统终止。
Inactive(不活跃的) 该应用程序在前台运行,但目前没有接收到事件。(不过,它可能正在执行其他代码。)一个应用程序在过渡到另一个状态时通常只停留在这个状态。
Active 应用程序正在前台运行,正在接收事件。这是前台应用程序的正常模式。
Background 该应用程序位于后台并执行代码。大多数应用程序都是暂时进入这个状态,然后被暂停。但是,请求额外执行时间的应用程序可能会在这个状态中停留一段时间。另外,一个直接进入后台的应用程序将进入这个状态而不是处于非活动状态。有关如何在后台执行代码的信息,请参见 后台执行
Suspended(暂停) 该应用程序位于后台,但不执行代码。系统会自动将应用程序移动到这个状态,并且在这样做之前不会通知他们。暂停时,应用程序仍在内存中,但不执行任何代码。
当出现低内存的情况时,系统可以在没有通知的情况下清除暂停的应用程序,从而为前台应用提供更多的空间。
图2-3

大多数状态转换都伴随着对应用程序委托对象的方法的相应调用。这些方法是您以适当的方式响应状态变化的机会。下面列出了这些方法,以及如何使用它们的摘要。

app 终止

应用程序必须随时准备终止,并且不应该等待保存用户数据或执行其他关键任务。系统启动的终止是应用程序生命周期的正常部分。该系统通常会终止应用程序,以回收内存,为用户启动的其他应用程序腾出空间,但该系统也可能会终止那些行为不端的应用程序,或者不及时响应事件。

被终止的应用程序在被终止时没有收到通知;系统杀死进程并回收相应的内存。如果一个应用程序在后台运行,而不是挂起,系统就会在终止之前调用它的应用程序委托。当设备重新启动时,系统不会调用此方法。

除了终止你的应用程序,用户还可以使用多任务用户界面终止你的应用程序。用户发起的终止与终止应用程序有相同的效果。应用程序的进程被杀死,没有通知被发送到应用程序。

线程和并发

系统创建您的应用程序的主线程,您可以根据需要创建额外的线程来执行其他任务。对于iOS应用程序,首选的技术是使用Grand Central Dispatch (GCD)、操作对象和其他异步编程接口,而不是自己创建和管理线程。诸如GCD之类的技术可以让您定义您想要做的工作和您想要完成的任务,但是让系统决定如何最好地在可用的cpu上执行该工作。让系统处理线程管理简化了您必须编写的代码,从而更容易确保代码的正确性,并提供更好的总体性能。

在考虑线程和并发时,请考虑以下因素:

  • 涉及到视图、核心动画和许多其他UIKit类的工作通常必须出现在应用程序的主线程上。这个规则也有一些例外,例如,基于映像的操作经常发生在后台线程上,但是当有疑问时,假设工作需要在主线程上发生。

  • 长任务(或可能的长度任务)应该始终在后台线程上执行。任何涉及网络访问、文件访问或大量数据处理的任务都应该使用GCD或操作对象异步执行。

  • 在启动时,尽可能在主线程上移动任务。在启动时,您的应用程序应该使用可用的时间来尽快设置它的用户界面。只有那些有助于设置用户界面的任务才应该在主线程上执行。所有其他任务都应该异步执行,当用户准备好后,结果显示给用户。

有关使用GCD和操作对象执行任务的更多信息,请参见并发编程指南

免责声明:以上内容均来自官方文档 iOS App 编程指南,在 有道翻译 的基础上进行修改整理,仅用于个人学习。因个人水平有限,如果存在错误,请读者谅解并指出,非常感谢!

相关文章

网友评论

    本文标题:App的生命周期

    本文链接:https://www.haomeiwen.com/subject/euuslftx.html