Application 的生命周期

來自 CocoaChina,加一些自己的認(rèn)識(shí)边败。

1慈缔、應(yīng)用程序的狀態(tài)

  • Not running未運(yùn)行:程序沒啟動(dòng)叮称。
  • Inactive未激活:程序在前臺(tái)運(yùn)行,不過沒有接收到事件藐鹤。在沒有事件處理情況下程序通常停留在這個(gè)狀態(tài)瓤檐。
  • Active激活:程序在前臺(tái)運(yùn)行而且接收到了事件。這也是前臺(tái)的一個(gè)正常的模式娱节。
  • Backgroud后臺(tái):程序在后臺(tái)而且能執(zhí)行代碼挠蛉,大多數(shù)程序進(jìn)入這個(gè)狀態(tài)后會(huì)在在這個(gè)狀態(tài)上停留一會(huì)。時(shí)間到之后會(huì)進(jìn)入掛起狀態(tài)(Suspended)肄满。有的程序經(jīng)過特殊的請(qǐng)求后可以長期處于Backgroud狀態(tài)谴古。
  • Suspended掛起:程序在后臺(tái)不能執(zhí)行代碼。系統(tǒng)會(huì)自動(dòng)把程序變成這個(gè)狀態(tài)而且不會(huì)發(fā)出通知稠歉。當(dāng)掛起時(shí)掰担,程序還是停留在內(nèi)存中的,當(dāng)系統(tǒng)內(nèi)存低時(shí)怒炸,系統(tǒng)就把掛起的程序清除掉带饱,為前臺(tái)程序提供更多的內(nèi)存。

2阅羹、各個(gè)程序運(yùn)行狀態(tài)時(shí)代理的回調(diào)

①告訴代理進(jìn)程啟動(dòng)但還沒進(jìn)入狀態(tài)保存

- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    NSLog(@"①告訴代理進(jìn)程啟動(dòng)但還沒進(jìn)入狀態(tài)保存"); 
    return YES; 
}

②告訴代理啟動(dòng)基本完成程序準(zhǔn)備開始運(yùn)行

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 
    NSLog(@"②告訴代理啟動(dòng)基本完成程序準(zhǔn)備開始運(yùn)行"); 
    // Override point for customization after application launch. 
    self.window.backgroundColor = [UIColor whiteColor]; 
    [self.window makeKeyAndVisible]; 
    return YES; 
} 

其中 launchOptions 是帶有啟動(dòng)參數(shù)的字典纠炮,存儲(chǔ)有此程序啟動(dòng)的原因月趟。launchOptions 中的鍵值對(duì)可以看 UIApplication Class Reference 中的 Launch Options Keys 一節(jié)。

若用戶直接啟動(dòng)恢口,launchOptions 內(nèi)無數(shù)據(jù);
若由其他應(yīng)用程序通過 openURL: 啟動(dòng)孝宗,則 UIApplicationLaunchOptionsURLKey 對(duì)應(yīng)的對(duì)象為啟動(dòng) URL(NSURL),UIApplicationLaunchOptionsSourceApplicationKey 對(duì)應(yīng)啟動(dòng)的源應(yīng)用程序的bundle ID (NSString)耕肩;
若由本地通知啟動(dòng)因妇,則 UIApplicationLaunchOptionsLocalNotificationKey 對(duì)應(yīng)的是為啟動(dòng)應(yīng)用程序的的本地通知對(duì)象(UILocalNotification);
若由遠(yuǎn)程通知啟動(dòng)猿诸,則 UIApplicationLaunchOptionsRemoteNotificationKey 對(duì)應(yīng)的是啟動(dòng)應(yīng)用程序的的遠(yuǎn)程通知信息 userInfo(NSDictionary)婚被;
其他key還有 UIApplicationLaunchOptionsAnnotationKey、UIApplicationLaunchOptionsLocationKey梳虽、
UIApplicationLaunchOptionsNewsstandDownloadsKey址芯。

如果要在啟動(dòng)時(shí),做出一些區(qū)分窜觉,那就需要在下面的代碼做處理谷炸。
比如應(yīng)用可以被某個(gè)其它應(yīng)用調(diào)起,那可能要在啟動(dòng)代碼的地方做出一些驗(yàn)證禀挫,比如以下例子旬陡。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    NSURL *url = [options objectForKey:UIApplicationLaunchOptionsURLKey];
    if (url) {
        // do something.
    }
    NSString *bundleId = [options objectForKey:UIApplicationLaunchOptionsSourceApplicationKey];
    if (bundleId) {
        // do something.
    }
    UILocalNotification * localNotify = [options objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
    if (localNotify) {
        // do something.
    }
    NSDictionary * userInfo = [options objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
    if (userInfo) {
        // do something.
    }
}

③當(dāng)應(yīng)用程序?qū)⒁敕腔顒?dòng)狀態(tài)執(zhí)行,在此期間语婴,應(yīng)用程序不接收消息或事件描孟,比如來電話

- (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(@"③當(dāng)應(yīng)用程序?qū)⒁敕腔顒?dòng)狀態(tài)執(zhí)行,在此期間砰左,應(yīng)用程序不接收消息或事件匿醒,比如來電話"); 
} 

④當(dāng)應(yīng)用程序進(jìn)入活動(dòng)狀態(tài)執(zhí)行

- (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(@"④當(dāng)應(yīng)用程序進(jìn)入活動(dòng)狀態(tài)執(zhí)行"); 
} 

⑤當(dāng)程序被推送到后臺(tái)的時(shí)候調(diào)用。所以要設(shè)置后臺(tái)繼續(xù)運(yùn)行缠导,則在這個(gè)函數(shù)里面設(shè)置即可

- (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(@"⑤當(dāng)程序被推送到后臺(tái)的時(shí)候調(diào)用"); 
    [application beginBackgroundTaskWithExpirationHandler:^{ 
        NSLog(@"begin Background Task With Expiration Handler"); 
    }]; 
}

⑥當(dāng)程序從后臺(tái)將要重新回到前臺(tái)時(shí)候調(diào)用

- (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(@"⑥當(dāng)程序從后臺(tái)將要重新回到前臺(tái)時(shí)候調(diào)用"); 
 }

⑦當(dāng)程序?qū)⒁顺鍪潜徽{(diào)用廉羔,通常是用來保存數(shù)據(jù)和一些退出前的清理工作。這個(gè)需要要設(shè)置UIApplicationExitsOnSuspend的鍵值

- (void)applicationWillTerminate:(UIApplication *)application { 
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 
    NSLog(@"⑦當(dāng)程序?qū)⒁顺鍪潜徽{(diào)用"); 
 }

⑧當(dāng)程序載入后執(zhí)行

- (void)applicationDidFinishLaunching:(UIApplication *)application { 
     NSLog(@"⑧當(dāng)程序載入后執(zhí)行"); 
 }

程序啟動(dòng)時(shí):
2014-07-01 15:55:14.706 LifeCycle[5845:60b] ①告訴代理進(jìn)程啟動(dòng)但還沒進(jìn)入狀態(tài)保存
2014-07-01 15:55:14.708 LifeCycle[5845:60b] ②告訴代理啟動(dòng)基本完成程序準(zhǔn)備開始運(yùn)行
2014-07-01 15:55:14.709 LifeCycle[5845:60b] ④當(dāng)應(yīng)用程序進(jìn)入活動(dòng)狀態(tài)執(zhí)行

按下Home鍵返回主界面:
2014-07-01 15:56:11.756 LifeCycle[5845:60b] ③當(dāng)應(yīng)用程序?qū)⒁敕腔顒?dòng)狀態(tài)執(zhí)行
2014-07-01 15:56:11.814 LifeCycle[5845:60b] ⑤當(dāng)程序被推送到后臺(tái)的時(shí)候調(diào)用

再次打開程序:
2014-07-01 15:57:19.200 LifeCycle[5845:60b] ⑥當(dāng)程序從后臺(tái)將要重新回到前臺(tái)時(shí)候調(diào)用
2014-07-01 15:57:19.201 LifeCycle[5845:60b] ④當(dāng)應(yīng)用程序進(jìn)入活動(dòng)狀態(tài)執(zhí)行


3酬核、加載應(yīng)用程序進(jìn)入前臺(tái)


4蜜另、加載應(yīng)用程序進(jìn)入后臺(tái)


5、基于警告式響應(yīng)中斷


當(dāng)出現(xiàn)這種中斷時(shí)嫡意,我們需要在- (void)applicationWillResignActive:(UIApplication *)application方法中進(jìn)行如下操作:

①停止timer 和其他周期性的任務(wù)

②停止任何正在運(yùn)行的請(qǐng)求

③暫停視頻的播放

④如果是游戲那就暫停它

⑤減少OpenGL ES的幀率

⑥掛起任何分發(fā)的隊(duì)列和不重要的操作隊(duì)列(你可以繼續(xù)處理網(wǎng)絡(luò)請(qǐng)求或其他時(shí)間敏感的后臺(tái)任務(wù))

當(dāng)程序回到active狀態(tài)举瑰,我們需要在- (void)applicationDidBecomeActive:(UIApplication *)application方法中重新開始上述任務(wù)。不過游戲要回到暫停狀態(tài)蔬螟,不能自動(dòng)開始此迅。


6、進(jìn)入后臺(tái)運(yùn)行


當(dāng)應(yīng)用程序進(jìn)入后臺(tái)時(shí),我們應(yīng)該做些什么耸序?

保存用戶數(shù)據(jù)或狀態(tài)信息忍些,所有沒寫到磁盤的文件或信息,在進(jìn)入后臺(tái)時(shí)坎怪,最后都寫到磁盤去罢坝,因?yàn)槌绦蚩赡茉诤笈_(tái)被殺死。

釋放盡可能釋放的內(nèi)存搅窿。

- (void)applicationDidEnterBackground:(UIApplication *)application

方法有大概5秒的時(shí)間讓你完成這些任務(wù)嘁酿。如果超過時(shí)間還有未完成的任務(wù),你的程序就會(huì)被終止而且從內(nèi)存中清除男应。

如果還需要長時(shí)間的運(yùn)行任務(wù)闹司,可以在該方法中調(diào)用

[application beginBackgroundTaskWithExpirationHandler:^{
    NSLog(@"begin Background Task With Expiration Handler");
}];

應(yīng)用程序在后臺(tái)時(shí)的內(nèi)存使用:請(qǐng)求后臺(tái)運(yùn)行時(shí)間和啟動(dòng)線程來運(yùn)行長時(shí)間運(yùn)行的任務(wù)。

在后臺(tái)時(shí)沐飘,每個(gè)應(yīng)用程序都應(yīng)該釋放最大的內(nèi)存游桩。系統(tǒng)努力的保持更多的應(yīng)用程序在后臺(tái)同時(shí) 運(yùn)行。不過當(dāng)內(nèi)存不足時(shí)耐朴,會(huì)終止一些掛起的程序來回收內(nèi)存借卧,那些內(nèi)存最大的程序首先被終止。

事實(shí)上隔箍,應(yīng)用程序應(yīng)該的對(duì)象如果不再使用了谓娃,那就應(yīng)該盡快的去掉強(qiáng)引用脚乡,這樣編譯器可以回收這些內(nèi)存蜒滩。如果你想緩存一些對(duì)象提升程序的性能,你可以在進(jìn)入后臺(tái)時(shí)奶稠,把這些對(duì)象去掉強(qiáng)引用俯艰。

下面這樣的對(duì)象應(yīng)該盡快的去掉強(qiáng)引用:

①圖片對(duì)象

②你可以重新加載的 大的視頻或數(shù)據(jù)文件

③任何沒用而且可以輕易創(chuàng)建的對(duì)象

在后臺(tái)時(shí),為了減少程序占用的內(nèi)存锌订,系統(tǒng)會(huì)自動(dòng)在回收一些系統(tǒng)幫助你開辟的內(nèi)存竹握。比如:

①系統(tǒng)回收Core Animation的后備存儲(chǔ)。

②去掉任何系統(tǒng)引用的緩存圖片

③去掉系統(tǒng)管理數(shù)據(jù)緩存強(qiáng)引用


7辆飘、返回前臺(tái)運(yùn)行

在暫停狀態(tài)的應(yīng)用程序必須準(zhǔn)備處理任何排隊(duì)的通知時(shí)啦辐,它返回到前臺(tái)或后臺(tái)執(zhí)行狀態(tài)。暫停的應(yīng)用程序不執(zhí)行任何代碼蜈项,因此不能處理與方向的變化芹关,時(shí)間的變化,偏好的變化紧卒,以及許多其他會(huì)影響應(yīng)用程序的外觀或狀態(tài)的通知侥衬。為了確保這些更改不會(huì)丟失,系統(tǒng)排隊(duì)許多相關(guān)的通知,并把它們傳遞給應(yīng)用程序轴总,只要它開始再次執(zhí)行代碼(無論是在前景或背景)直颅。為了防止由偏快轉(zhuǎn)為超載與它恢復(fù)時(shí)通知您的應(yīng)用程序,該系統(tǒng)凝聚事件怀樟,并提供一個(gè)單一的通知(每個(gè)相關(guān)類型)功偿,反映了凈變化,因?yàn)槟愕膽?yīng)用程序被暫停往堡。


8脖含、程序終止

程序只要符合以下情況之一,只要進(jìn)入后臺(tái)或掛起狀態(tài)就會(huì)終止:

①iOS4.0以前的系統(tǒng)

②app是基于iOS4.0之前系統(tǒng)開發(fā)的投蝉。

③設(shè)備不支持多任務(wù)

④在Info.plist文件中养葵,程序包含了 UIApplicationExitsOnSuspend 鍵。

app如果終止了瘩缆,系統(tǒng)會(huì)調(diào)用app的代理的方法 - (void)applicationWillTerminate:(UIApplication *)application关拒,這樣可以讓你可以做一些清理工作。你可以保存一些數(shù)據(jù)或app的狀態(tài)庸娱。這個(gè)方法也有5秒鐘的限制着绊。超時(shí)后方法會(huì)返回程序從內(nèi)存中清除。

注意:用戶可以手工關(guān)閉應(yīng)用程序熟尉。


9归露、The Main Run Loop 主運(yùn)行循環(huán)

Main Run Loop負(fù)責(zé)處理用戶相關(guān)的事件。UIApplication對(duì)象在程序啟動(dòng)時(shí)啟動(dòng)main run Loop斤儿,它處理事件和更新視圖的界面剧包。看Main Run Loop就知道往果,它是運(yùn)行在程序的主線程上的疆液。這樣保證了接收到用戶相關(guān)操作的事件是按順序處理的。

用戶操作設(shè)備陕贮,相關(guān)的操作事件被系統(tǒng)生成并通過UIKit的指定端口分發(fā)堕油。事件在內(nèi)部排成隊(duì)列,一個(gè)個(gè)的分發(fā)到Main run loop 去做處理肮之。UIApplication對(duì)象是第一個(gè)接收到時(shí)間的對(duì)象掉缺,它決定事件如何被處理。觸摸事件分發(fā)到主窗口戈擒,窗口再分發(fā)到對(duì)應(yīng)出發(fā)觸摸事件的View眶明。其他的事件通過其他途徑分發(fā)給其他對(duì)象變量做處理。

大部分的事件可以在你的應(yīng)用里分發(fā)峦甩,類似于觸摸事件赘来,遠(yuǎn)程操控事件(線控耳機(jī)等)都是由app的 responder objects 對(duì)象處理的现喳。Responder objects 在你的app里到處都是,比如:UIApplication 對(duì)象犬辰,view對(duì)象嗦篱,view controller 對(duì)象,都是resopnder objects幌缝。大部分事件的目標(biāo)都指定了resopnder object灸促,不過事件也可以傳遞給其他對(duì)象。比如涵卵,如果view對(duì)象不處理事件浴栽,可以傳給父類view或者view controller。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末轿偎,一起剝皮案震驚了整個(gè)濱河市典鸡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌坏晦,老刑警劉巖萝玷,帶你破解...
    沈念sama閱讀 221,430評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異昆婿,居然都是意外死亡球碉,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門仓蛆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來睁冬,“玉大人,你說我怎么就攤上這事看疙《共Γ” “怎么了?”我有些...
    開封第一講書人閱讀 167,834評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵狼荞,是天一觀的道長辽装。 經(jīng)常有香客問我帮碰,道長相味,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,543評(píng)論 1 296
  • 正文 為了忘掉前任殉挽,我火速辦了婚禮丰涉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘斯碌。我一直安慰自己一死,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,547評(píng)論 6 397
  • 文/花漫 我一把揭開白布傻唾。 她就那樣靜靜地躺著投慈,像睡著了一般承耿。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上伪煤,一...
    開封第一講書人閱讀 52,196評(píng)論 1 308
  • 那天加袋,我揣著相機(jī)與錄音,去河邊找鬼抱既。 笑死职烧,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的防泵。 我是一名探鬼主播蚀之,決...
    沈念sama閱讀 40,776評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼捷泞!你這毒婦竟也來了足删?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,671評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤锁右,失蹤者是張志新(化名)和其女友劉穎壹堰,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體骡湖,經(jīng)...
    沈念sama閱讀 46,221評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡贱纠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,303評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了响蕴。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谆焊。...
    茶點(diǎn)故事閱讀 40,444評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖浦夷,靈堂內(nèi)的尸體忽然破棺而出辖试,到底是詐尸還是另有隱情,我是刑警寧澤劈狐,帶...
    沈念sama閱讀 36,134評(píng)論 5 350
  • 正文 年R本政府宣布罐孝,位于F島的核電站,受9級(jí)特大地震影響肥缔,放射性物質(zhì)發(fā)生泄漏莲兢。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,810評(píng)論 3 333
  • 文/蒙蒙 一续膳、第九天 我趴在偏房一處隱蔽的房頂上張望改艇。 院中可真熱鬧,春花似錦坟岔、人聲如沸谒兄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,285評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽承疲。三九已至邻耕,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間燕鸽,已是汗流浹背赊豌。 一陣腳步聲響...
    開封第一講書人閱讀 33,399評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留绵咱,地道東北人碘饼。 一個(gè)月前我還...
    沈念sama閱讀 48,837評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像悲伶,于是被迫代替她去往敵國和親艾恼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,455評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容