App的生命周期
App从启动到退出的过程中,iOS应用程序不断从系统接收各种事件,如:用户点击了屏幕、用户点击了Home
键,并对这些事件进行响应。接受事件是UIApplication
对象的工作,但是,响应事件就需要由程序员编写的代码来处理。为了理解事件响应需要在哪里处理,就必须对iOS应用程序的整个生命周期和事件周期有所了解。
主函数main()
main()
函数是每个iOS程序的入口,但在实际开发中,基本不需要在main()
函数中进行额外的处理。在main
中,最核心的功能就是把应用程序的控制权交给UIKit框架,其中UIApplicationMain
函数主要完成以下3个工作:
- 创建应用程序所需的核心对象
- 读取
storyboard
文件,来加载用户界面 - 调用自定义的代码,用来定制应用程序的启动过程
#import <UIKit/UIKit.h>
#import "AppDelegate.h"int main(int argc, char * argv[]) {NSString * appDelegateClassName;@autoreleasepool {// Setup code that might create autoreleased objects goes here.appDelegateClassName = NSStringFromClass([AppDelegate class]);}return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}
应用程序的状态
在iOS4之后,苹果引入了多任务功能,因此,对于应用程序来说运行过程中就存在多种状态以及在不同状态之间的相互切换。应用程序一共存在下列五种状态,如图:
Not Running
(未运行):应用程序未启动或者被终止。Inactive
(待激活):应用程序在前台运行,但是不能接收事件(UIEvent)
。应用程序在不同状态之间切换时,经常会存在该状态。例如:在App显示启动页时,是从Not Running
到Active
的过程,中间会存在Inactive
状态。Active
(激活,前台运行):应用程序在前台运行,可以接收事件(UIEvent)
。Background
(后台运行):应用程序处于后台并且正在执行代码。绝大多数应用程序在进入挂起状态时,会短暂经历这个状态。Suspended
(挂起):应用程序处于后台,并且不能执行代码。此时,当内存不足时,操作系统有可能会自动把挂起状态的应用程序移除,以便给处于Active
状态的应用程序提供更多的内存空间。
应用程序的启动过程
当用户点击icon
的时候,应用程序会经历:NotRunning→Inactive→Active
的过程,如图所示。在这个过程中,AppDelegete
对象的如下方法会被调用。
在实际开发过程中,假如不需要通过storyboard
加载界面,那么就需要在di dFinishLaunchingWithOptions:
方法中,设置window
的根控制器。
应用程序从前台切换到后台
当用户点击Home
键的时候,应用程序会经历Active → Background →Suspended
过程。在这个时候,会调用AppDelegate
对象中的application WillResignActive:
以及applicationEnterBackgroud:
方法。在实际的开发过程中,当用户点击Home
键使用程序切换到后台时,需要在这些方法中对数据或者状态进行保存,如图所示。
默认状态下,applicationEnterBackgroud:
大概有5秒事件来完成一些任务。假如说5秒的时间不够,则需要调用beginBackgroundTaskWithExpirationHandler:
方法来申请更多的后台运行时间,后台运行的时间由backgroundTimeRemaining
属性来确定。
应用程序从后台切换到前台
当应用程序从后台切换到前台时,会调用applicationWillEnterForeground:
以及applicationDidBecomeActive:
方法,如下图。
响应中断
当来电或者闹钟触发的时候,应用程序会触发中断,这时AppDelegate
对象会先调用applicationWillResignActive:
方法,当用户接听电话时,会直接跳转到电话程序;假如用户选择不接听电话,这时会返回应用程序,并调用applicationDidBecomeActive:
方法,如图所示。
锁屏/解锁
当用户锁屏的时候,应用程序会调用AppDelegate
对象的applicationWillResignActive:
方法以及applicationDidEnterBackground:
方法。当用户解锁后,应用程序会调用applicationWillEnterForeground:
方法以及applicationDidBecomeActive:
方法。
小结
要知道APP的生命周期,首先要了解一下生命周期的5种状态,结合状态理解生命周期的使用。
应用的状态包括:
-
未运行(Not running)
程序没启动 -
未激活(Inactive)
程序在前台运行,不过没有接收到事件。
一般每当应用要从一个状态切换到另一个不同的状态时,中途过渡会短暂停留在此状态。唯一在此状态停留时间比较长的情况是:当用户锁屏时,或者系统提示用户去响应某些(诸如电话来电、有未读短信等)事件的时候。 -
激活(Active)
程序在前台运行而且接收到了事件。这也是前台的一个正常的模式 -
后台(Backgroud)
程序在后台而且能执行代码,大多数程序进入这个状态后会在在这个状态上停留一会。时间到之后会进入挂起状态(Suspended)。有的程序经过特殊的请求后可以长期处于Backgroud状态 -
挂起(Suspended)
程序在后台不能执行代码。系统会自动把程序变成这个状态而且不会发出通知。当挂起时,程序还是停留在内存中的,当系统内存低时,系统就把挂起的程序清除掉,为前台程序提供更多的内存。
APP的生命周期就是UIApplicationDelegate中的回调方法,这些方法是根据状态变化进行响应的地方,其中最常用的就是以下7个方法:
application:willFinishLaunchingWithOptions:
在App启动时调用表示应用加载进程已经开始,常用来处理应用状态的存储和恢复
application:didFinishLaunchingWithOptions:
表示App将从未运行状态进入运行状态,用于对App的初始化操作
applicationDidBecomeActive:
当应用即将进入前台运行时调用
applicationWillResignActive:
当应用即将进从前台退出时调用
applicationDidEnterBackground:
当应用开始在后台运行的时候调用
applicationWillEnterForeground:
当程序从后台将要重新回到前台(但是还没变成Active状态)时候调用
applicationWillTerminate:
当前应用即将被终止,在终止前调用的函数。通常是用来保存数据和一些退出前的清理工作。如果应用当前处在suspended
,此方法不会被调用。 该方法最长运行时限为5秒,过期应用即被kill掉并且移除内存。
参考:
iOS app生命周期
《iOS开发:从零基础到精通》
最后我们来看看chatGPT如何总结的:
int main(int argc, char * argv[]) {@autoreleasepool {return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));}
}- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];// 创建根视图控制器UIViewController *rootViewController = [[UIViewController alloc] init];self.window.rootViewController = rootViewController;// 显示主窗口[self.window makeKeyAndVisible];return YES;
}- (void)viewDidLoad {[super viewDidLoad];// 加载数据、配置视图等
}- (void)viewWillAppear:(BOOL)animated {[super viewWillAppear:animated];// 视图即将显示
}- (void)viewDidAppear:(BOOL)animated {[super viewDidAppear:animated];// 视图已经显示
}