程序入口 main

在 C 语言中,一个程序的入口总是从 main 函数开始。 iOS 也是一样,不同的是,在创建项目的过程中 Xcode 已经自动帮我们生成了代码,因此在 iOS 中我们不用自己编写 main 函数功能 。而且每个创建好的 iOS 工程目录当中都会见到这个文件: main.m

在双击打开这个文件可以看到代码:

在 iOS 中,main 唯一的功能是控制 UIKit 框架。在上图代码中看到,调用了一个 UIApplicationMain 方法:

UIApplication

一个 APP 和一个 UIApplication 实例是等价的,一个 UIApplication 对象就代表一个应用程序。

根据 UIApplication 方法的定义:

  • argcargv:是 ISO C 标准 main 函数的参数,作用是直接传递给 UIApplicationMain 进行相关处理。它包含应用程序何时从系统启动等信息。这些参数是由 UIKit 控制,我们不应该改动它们。
  • principalClassName : 它用来指定应用程序的类名,这类名必须继承 UIApplication 或者是 UIApplication 的子类,如果传 nil 时候就默认使用 UIApplication 这个类名。
  • delegateClassName: 这个类指定一个应用程序的代理,这个必须遵守 UIApplication delegate 的协议,可以看到 main.m 文件开头包含了一个 AppDelegeate.h 头文件,这个就是 UIApplication 的 delegate 协议文件。

我们重点看到 delegateClassName: UIApplication 的主要任务负责在模拟器或者手机上显示第一个 UIView ,另外一个任务是帮助系统管理应用程序,而这个 delegateClassName 参数就是指定需要由谁来,委托谁来当这个“角色”。这里 Xcode 已经帮我们指定了一个叫做 [Appdelegate class] 值, main.m 文件 import 了一个 AppDelegeate.h 头文件,也是这个原理。

AppDelegate

几乎,系统与 APP 之间所有的交互关系都依赖这个 AppDelegate 来传递

  • 管理应用程序生命周期

    生命周期,通俗说应该是应用程序的活动状态,它包含以下 5 种:

    1. Not running: 该 App 尚未被用户或系统启动或终止。
    2. Inactive: App 在前台运行,但没有接收事件。(它可能正在执行其他代码)。App 通常只在转换到不同状态时保持这种状态。当进入这个状态时,App 应该将自己放入一个 Suspended 状态,期望在不久的将来移动到背景或活动状态。
    3. Active:应用程序在前台运行并接收事件。这是应用程序的正常模式。处于活动状态的应用程序对它没有特别的限制。它是前台应用程序,应该对用户作出响应。
    4. Background:应用程序正在执行代码,但屏幕上不可见。当用户退出应用程序时,系统会在暂停之前将应用程序移动到后台状态。在其他时候,系统可能将应用程序启动到后台(或唤醒一个暂停的应用程序),并给它时间处理特定的任务。例如,系统可能唤醒一个应用程序,以便它能够处理后台下载、某些类型的位置事件、远程通知和其他类型的事件。背景状态下的应用程序应该尽可能少地工作。请求时间处理特定类型事件的应用程序应该处理这些事件,并尽快将控制权返回给系统。
    5. Suspended:该应用程序在后台,不执行代码。系统会自动将后台状态的应用程序移动到此状态,并且不会告知他们。虽然暂停了,不过应用程序仍然在内存中,不会执行代码。当出现内存不足的情况时,系统会在不通知的情况下清除掉暂停状态的应用程序,为系统或者前台应用程序空出内存空间。

有了以上的知识铺垫之后我们就可以来做一些实践,一般 App 首次从系统界面进入到 App 页面,系统会开启一个进程和主线程,通过调用 main 函数创建属于这个 App 的 UIApplication 单例对象。并委托 AppDelegate 执行 application:willFinishLaunchingWithOptions: 和 application:didFinishLaunchingWithOptions: 方法检查 App 在出现屏幕之前会与系统发生哪些行为交互,如了解启动的原因等。从而完成启动。

application:willFinishLaunchingWithOptions: 和 application:didFinishLaunchingWithOptions: 方法应该尽可能轻巧减少 App 的启动时间。App 预计将启动、初始化,并在不到5秒的时间内开始处理事件。如果一个 App 没有及时完成它的发布周期,系统就会认为没有响应而终止运行。因此,任何可能减慢启动(例如访问网络)的任务都应在次要线程上执行。

除此之外他还有个 applicationDidFinishLaunching: ,这个方法同样可以做到启动 app 到显示界面的效果,唯独不执行 application:willFinishLaunchingWithOptions: 这个方法,苹果开发文档不推荐使用这个方法来完成 App 启动。

然而启动之后 App 并不会立刻显示到界面。当你的应用程序启动前,它处于 Not running 状态,通过执行 application:willFinishLaunchingWithOptions: 和 application:didFinishLaunchingWithOptions: 两个方法指定 App 要置为 Active 状态或 Background状态。默认情况下会选择 Active 状态,即屏幕能看到 App 界面,。以下即流程图

当状态转换发生时会调用以下方法:

  • 转到前台(Active):applicationDidBecomeActive:
  • 转到背景 (Background):applicationDidEnterBackground:
  • 转到非活动状态 (Inactive):
    • applicationWillResignActive: (离开前景状态时调用。)
    • applicationWillEnterForeground:(从后台状态转换时调用。)
  • 结束 App:applicationWillTerminate:

有关状态切换运行,请看以下操作视频。相关函数代码还请读者手动实践,细心体会。

App 运行状态展示

参考阅读:

The App Life Cycle

Strategies for Handling App State Transitions

发表评论

电子邮件地址不会被公开。 必填项已用*标注