應用程序的狀態
IOS的應用程序一共有5種狀態。
- Not running(未運行):程序未啟動
- Inactive(未激活):其他兩個狀態切換時出現的短暫狀態。唯一在此狀態停留時間比較長的情況是:當用戶鎖屏時?或者系統提示用戶去響應Alert窗口(如來電、信息)時
- Active(激活):在屏幕上顯示的正常運行狀態,該狀態下可以接收用戶輸入並更新顯示
- Backgroud(后台):程序在后台且能執行代碼。用戶按下Home鍵不久后進入此狀態(先進入了Inactive狀態,再進入Background狀態),然后會迅速進入掛起狀態(Suspended)。有的程序經過特殊的請求后可以長期處於Backgroud狀態
- Suspended(掛起):程序在后台不能執行代碼。普通程序在進入Background狀態不久后就會進入此狀態。當掛起時,程序還是停留在內存中的,當系統內存低時,系統就把掛起的程序清除掉,為前台程序提供更多的內存
這個圖非常重要,每一個箭頭都需要細細研讀。
關於Active和Inactive的切換:
應用程序在前台時有2種狀態:Active和Inactive。大多數情況下,Inactive狀態只是其他兩個狀態切換時出現的短暫狀態(不是任意兩個狀態之間的切換都會進入Inactive,見圖),如打開應用,它會從Not Running先進入Inactive再進入Active;如前后台應用切換時,Inactive會在Active和Background之間短暫出現。
但是也有其他情況,Active和Inactive可以在前台運行時進行切換,比如系統彈出Alert,此時應用會從Active切換到Inactive,直到用戶確認再返回Actvie;再如用戶拉下通知頁,也會發生Active和Inactive的切換;還有來電但拒接、雙擊Home鍵但返回原應用等都不進入Background,而只是在Active和Inactive切換。
如圖,是否可以這樣說,要想進入Active必須先進入Inactive。
入口函數
int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([XYZAppDelegate class])); } }
// If nil is specified for principalClassName, the value for NSPrincipalClass from the Info.plist is used. If there is no // NSPrincipalClass key specified, the UIApplication class is used. The delegate class will be instantiated using init. UIKIT_EXTERN int UIApplicationMain(int argc, char *argv[], NSString *principalClassName, NSString *delegateClassName);
argc和argv是為了與C語言保持一致,在這沒用到,不詳述。
后面兩個參數為principalClassName(主要類名)和delegateClassName(委托類名)。
如果principalClassName是nil,那么它的值將從Info.plist中獲取,如果Info.plist中沒有,則默認為UIApplication。principalClass這個類除了管理整個程序的生命周期之外什么都不做,它只賦值監聽事件然后交給delegateClass去做。
而delegateClass將在工程新建時實例化一個對象。
NSStringFromClass([XYZAppDelegate class])
相當於@"XYZAppDelegate"。
AppDelegate類六個方法
注意代碼中的官方注釋。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. NSLog(@"didFinishLaunchingWithOptions"); return YES; } - (void)applicationWillResignActive:(UIApplication *)application { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. NSLog(@"WillResignActive"); } - (void)applicationDidEnterBackground:(UIApplication *)application { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. NSLog(@"DidEnterBackground"); } - (void)applicationWillEnterForeground:(UIApplication *)application { // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. NSLog(@"WillEnterForeground"); } - (void)applicationDidBecomeActive:(UIApplication *)application { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. NSLog(@"DidBecomeActive"); } - (void)applicationWillTerminate:(UIApplication *)application { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. NSLog(@"WillTerminate"); }
啟動程序
2014-07-28 15:22:39.883 LifeCycle[3024:a0b] didFinishLaunchingWithOptions
2014-07-28 15:22:39.887 LifeCycle[3024:a0b] DidBecomeActive
按下Home鍵
2014-07-28 15:22:43.130 LifeCycle[3024:a0b] WillResignActive
2014-07-28 15:22:43.131 LifeCycle[3024:a0b] DidEnterBackground
重新點擊程序
2014-07-28 15:22:44.380 LifeCycle[3024:a0b] WillEnterForeground
2014-07-28 15:22:44.380 LifeCycle[3024:a0b] DidBecomeActive
注意:
- 啟動程序並沒有調用WillEnterForeground這個方法。
- 並不是所有狀態切換都有相應的方法來通知,比如從Background到Suspended。所以當你按下Home鍵的時候,我們只知道調用了WillResignActive和DidEnterBackground方法,但其實應用程序會迅速從Background進入Suspended。
1.application:didFinishLaunchingWithOptions:
程序首次已經完成啟動時執行,若直接啟動,launchOptions中沒有數據;否則,launchOptions將包含對應方式的內容(比如從微信中啟動節奏大師--)。
2.applicationWillResignActive(將進入后台)
程序將要失去Active狀態時調用,比如按下Home鍵或有電話信息進來。對應applicationWillEnterForeground(將進入前台),這個方法用來
- 暫停正在執行的任務;
- 禁止計時器;
- 減少OpenGL ES幀率;
- 若為游戲應暫停游戲;
總結為一個字:停!
3.applicationDidEnterBackground(已經進入后台)
程序已經進入后台時調用,對應applicationDidBecomeActive(已經變成前台),這個方法用來
- 釋放共享資源;
- 保存用戶數據(寫到硬盤);
- 作廢計時器;
- 保存足夠的程序狀態以便下次恢復;
總結為4個字:釋放、保存!
4.applicationWillEnterForeground(將進入前台)
程序即將進去前台時調用,對應applicationWillResignActive(將進入后台)。這個方法用來撤銷applicationWillResignActive中做的改變。
5.applicationDidBecomeActive(已經進入前台)
程序已經變為Active(前台)時調用。對應applicationDidEnterBackground(已經進入后台)。若程序之前在后台,最后在此方法內刷新用戶界面。
6.applicationWillTerminate
程序即將退出時調用。記得保存數據,如applicationDidEnterBackground方法一樣。
如果你的類是AppDelegate類(聲明遵循UIApplicationDelegate協議),那么可以實現上面的6個方法,當App狀態改變的時候相應的方法會被調用;如果你的類不是AppDelegate類,那么該類如何知道App的各種狀態變化,以及如何使用這些函數呢?答案是使用NotificationCenter來通知。
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive) name:UIApplicationWillResignActiveNotification object:[UIApplication sharedApplication]];
然后實現applicationWillResignActive就行了
- (void)applicationWillResignActive //自定義的函數 { NSLog(@"%@", NSStringFromSelector(_cmd)); }