前言
網(wǎng)上有很多關(guān)于程序啟動(dòng)過程和UIApplicationDelegate方法調(diào)用順序的文章膏秫。筆者這里不再介紹程序的啟動(dòng)過程和delegate方法的調(diào)用過程白华。而是介紹一下UIApplication會(huì)在什么情況下調(diào)用UIApplicationDelegate的哪些方法屯烦。以及常見的場景下凉当,哪些方法會(huì)被調(diào)用茄靠,蘋果為什么會(huì)這樣做璧榄。
回顧
首先讓我們先來回顧下與程序啟動(dòng)過程相關(guān)的一些delegate方法的調(diào)用時(shí)機(jī)特漩。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSLog(@"程序啟動(dòng)完成:%s",__func__);
return YES;
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
NSLog(@"已經(jīng)獲得焦點(diǎn):%s",__func__);
}
- (void)applicationWillResignActive:(UIApplication *)application {
NSLog(@"將要釋放焦點(diǎn):%s",__func__);
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
NSLog(@"已經(jīng)進(jìn)入后臺(tái):%s",__func__);
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
NSLog(@"將要進(jìn)入前臺(tái):%s",__func__);
}
- (void)applicationWillTerminate:(UIApplication *)application {
NSLog(@"程序?qū)⒁顺觯?s",__func__);
}
情景一 程序啟動(dòng)
程序被加載到內(nèi)存,完成啟動(dòng)骨杂,application對(duì)象會(huì)自動(dòng)調(diào)用delegate的下面這個(gè)方法涂身,證明程序已經(jīng)啟動(dòng)完成
。所以這個(gè)方法也是首先會(huì)被application回調(diào)的方法搓蚪,且這個(gè)方法在整個(gè)程序的生命周期中只會(huì)被調(diào)用一次蛤售。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
程序啟動(dòng)時(shí),回調(diào)完上面的方法妒潭,會(huì)繼續(xù)回調(diào)delegate的已經(jīng)獲得了焦點(diǎn)的方法悴能,證明程序已經(jīng)獲得了焦點(diǎn)
。
- (void)applicationDidBecomeActive:(UIApplication *)application雳灾;
```
>結(jié)論:應(yīng)用啟動(dòng)過程中漠酿,會(huì)依次調(diào)用delegate已經(jīng)啟動(dòng)完成和已經(jīng)獲得焦點(diǎn)的方法,不會(huì)調(diào)用已經(jīng)進(jìn)入前臺(tái)的方法谎亩。
#### 情景二 程序從前臺(tái)退出到后臺(tái)
當(dāng)程序處于前臺(tái)時(shí),單擊home鍵炒嘲,程序會(huì)自動(dòng)退出到后臺(tái)。在這個(gè)過程中匈庭,程序會(huì)先回調(diào)delegate的將要失去焦點(diǎn)的方法夫凸,證明程序**`將要失去焦點(diǎn)`**。
```
- (void)applicationWillResignActive:(UIApplication *)application;
```
調(diào)用調(diào)用完上面的方法后阱持,程序緊接著會(huì)調(diào)用delegate已經(jīng)進(jìn)入后臺(tái)的方法夭拌,證明**`程序已經(jīng)進(jìn)入后臺(tái)`**。
```
- (void)applicationDidEnterBackground:(UIApplication *)application;
```
> 結(jié)論:單擊home鍵進(jìn)入后臺(tái)會(huì)依次調(diào)用delegate的將要失去焦點(diǎn)的方法和已經(jīng)進(jìn)入后臺(tái)的方法衷咽。
####情景三 程序從后臺(tái)進(jìn)入到前臺(tái)
(4)從后臺(tái)進(jìn)入前臺(tái)(無論是雙擊home鍵進(jìn)入或者點(diǎn)擊應(yīng)用圖標(biāo)進(jìn)入)鸽扁,會(huì)回調(diào)delegate的將要進(jìn)入前臺(tái)方法,證明**`程序?qū)⒁M(jìn)入前臺(tái)`**镶骗。
```
- (void)applicationWillEnterForeground:(UIApplication *)application;
```
回調(diào)完上面的方法桶现,緊接著會(huì)繼續(xù)回調(diào)delegate的已經(jīng)獲得焦點(diǎn)的方法,證明程序**`已經(jīng)獲得了焦點(diǎn)`**卖词。
```
- (void)applicationDidBecomeActive:(UIApplication *)application;
```
> 結(jié)論:從后臺(tái)進(jìn)入前臺(tái),會(huì)依次調(diào)用delegate的將要進(jìn)入前臺(tái)和已經(jīng)獲得焦點(diǎn)的方法此蜈。
#### 情景四 雙擊home鍵切換程序
在前臺(tái)即横,雙擊home鍵,只會(huì)調(diào)用delegate的將要失去焦點(diǎn)的方法裆赵,證明```程序?qū)⒁ソ裹c(diǎn)```东囚。
```
- (void)applicationWillResignActive:(UIApplication *)application;
```
當(dāng)用戶真正切換應(yīng)用時(shí)候,才會(huì)繼續(xù)調(diào)用delegate的已經(jīng)進(jìn)入后臺(tái)的方法战授,證明**`程序已經(jīng)進(jìn)入后臺(tái)`**页藻。
```
- (void)applicationDidEnterBackground:(UIApplication *)application;
```
> 結(jié)論:雙擊home鍵切換應(yīng)用。會(huì)分別調(diào)用程序?qū)⒁ソ裹c(diǎn)的方法和程序已經(jīng)進(jìn)入后臺(tái)的方法植兰。 且這兩個(gè)方法是分開調(diào)用的份帐。即,雙擊home鍵時(shí)調(diào)用將要失去焦點(diǎn)的方法楣导,選擇其他應(yīng)用時(shí)調(diào)用已經(jīng)進(jìn)入后臺(tái)的方法废境。
####情景五 在前臺(tái)雙擊home鍵殺死程序
雙擊home鍵時(shí),只會(huì)調(diào)用delegate的將要失去焦點(diǎn)的方法(上面已經(jīng)說過),證明程序?qū)⒁ソ裹c(diǎn)筒繁。
```
- (void)applicationWillResignActive:(UIApplication *)application;
```
然后手指上滑殺死程序噩凹,會(huì)直接調(diào)用delegate的已經(jīng)進(jìn)入后臺(tái)的方法,證明程序已經(jīng)進(jìn)入后臺(tái)毡咏。
```
- (void)applicationDidEnterBackground:(UIApplication *)application;
```
然后緊接著調(diào)用delegate的程序?qū)⒁顺龅姆椒ㄍ匝纾C明程序?qū)⒁粴⑺馈?- (void)applicationWillTerminate:(UIApplication *)application;
> 結(jié)論:雙擊home鍵然后殺死程序,會(huì)按照如下順序調(diào)用delegate的方法:
```
- (void)applicationWillResignActive:(UIApplication *)application;(雙擊home鍵調(diào)用)
```
```
- (void)applicationDidEnterBackground:(UIApplication *)application;(殺死程序時(shí)調(diào)用這兩個(gè)方法)
- (void)applicationWillTerminate:(UIApplication *)application;
```
####情景六 從其他程序前臺(tái)雙擊home鍵殺死后臺(tái)程序
如果從其他程序的前臺(tái)呕缭,雙擊home鍵殺死后臺(tái)程序堵泽,被殺死程序只會(huì)回調(diào)delegate即將退出的方法。
```
- (void)applicationWillTerminate:(UIApplication *)application;
```
**為什么呢臊旭?**
因?yàn)槲覀兪菑囊粋€(gè)前臺(tái)程序殺死一個(gè)后臺(tái)程序落恼,這個(gè)后臺(tái)程序當(dāng)初進(jìn)入后臺(tái)時(shí)候已經(jīng)調(diào)用了將要釋放焦點(diǎn)和已經(jīng)進(jìn)入后臺(tái)的方法,所以殺死時(shí)候只會(huì)回調(diào)delegate即將終結(jié)的方法离熏。
> 結(jié)論:從一個(gè)前臺(tái)程序殺死一個(gè)后臺(tái)程序佳谦。后臺(tái)程序只會(huì)回調(diào)delegate的程序即將退出的方法。
---
####情景七 下拉通知欄
下拉通知欄滋戳,只會(huì)回調(diào)delegate的程序?qū)⒁尫沤裹c(diǎn)的方法钻蔑。程序并沒有進(jìn)入后臺(tái),所以不會(huì)調(diào)用進(jìn)入后臺(tái)的方法
```
- (void)applicationWillResignActive:(UIApplication *)application;
```
結(jié)論:下拉狀態(tài)欄只會(huì)讓程序失去焦點(diǎn)奸鸯,并不會(huì)讓程序進(jìn)入后臺(tái)咪笑。
因?yàn)橄吕ㄖ獧谥徽{(diào)用了將要釋放焦點(diǎn)的方法,沒有調(diào)用進(jìn)入后臺(tái)方法娄涩,所以收起通知欄時(shí)窗怒,只會(huì)調(diào)用已經(jīng)獲得焦點(diǎn)的方法映跟,不會(huì)調(diào)用進(jìn)入前臺(tái)的方法。
```
- (void)applicationDidBecomeActive:(UIApplication *)application扬虚;
```
同樣努隙,從屏幕下方向上滑動(dòng)屏幕,喚出工具欄時(shí)候辜昵,也只會(huì)調(diào)用delegate的將要釋放焦點(diǎn)的方法荸镊。收起工具欄時(shí),只會(huì)調(diào)用delegate的已經(jīng)獲得焦點(diǎn)的方法堪置。
> 結(jié)論:下拉通知欄或者上拉工具欄躬存,都只是回調(diào)delegate的即將釋放焦點(diǎn)的方法,程序不會(huì)進(jìn)入后臺(tái)舀锨。
## 為什么
當(dāng)初學(xué)習(xí)iOS時(shí)候岭洲,對(duì)這個(gè)地方不是很清楚,總是搞不懂為什么程序的delegate有一個(gè)將要進(jìn)入前臺(tái)的方法`applicationWillEnterForeground:`雁竞,卻沒有類似于`applicationDidEnterForeground:`的已經(jīng)進(jìn)入前臺(tái)的方法(純屬捏造)钦椭?為什么程序的delegate有一個(gè)已經(jīng)進(jìn)入后臺(tái)的方法`applicationDidEnterBackground:`卻沒有一個(gè)類似于`applicationWillEnterBackground:`的將要進(jìn)入后臺(tái)的方法?為什么進(jìn)入前臺(tái)時(shí)碑诉,方法的調(diào)用順序是`applicationWillEnterForeground:`和`applicationDidBecomeActive:`而不是相反彪腔?這些問題一直困擾著我。
**將要進(jìn)入前臺(tái)进栽、已經(jīng)獲得焦點(diǎn)德挣、將要失去焦點(diǎn)、已經(jīng)進(jìn)入后臺(tái)**這幾個(gè)方法是比較容易混淆的快毛,且調(diào)用順序經(jīng)常被搞混格嗅。但是如果理解了蘋果為什么這么設(shè)計(jì),這些困惑都將迎刃而解唠帝。重點(diǎn)來了:如果一個(gè)應(yīng)用程序失去焦點(diǎn)那么意味著用戶當(dāng)前無法進(jìn)行交互操作屯掖,正因如此,程序從前臺(tái)退出到后臺(tái)時(shí)候襟衰,一般會(huì)**先失去焦點(diǎn)再進(jìn)入后臺(tái)**避免進(jìn)入后臺(tái)過程中用戶還可以和程序進(jìn)行交互贴铜。同理,一個(gè)應(yīng)用程序從后臺(tái)進(jìn)入前臺(tái)也是類似的瀑晒,會(huì)**先進(jìn)入前臺(tái)再獲得焦點(diǎn)**绍坝,這樣進(jìn)入前臺(tái)過程中未完全準(zhǔn)備好的情況下用戶無法操作,保證了程序的安全性苔悦。
至于為什么蘋果沒有提供類似于`applicationDidEnterForeground:`的已經(jīng)進(jìn)入前臺(tái)的方法轩褐,那是因?yàn)槌绦蜻M(jìn)入前臺(tái)后必定會(huì)回調(diào)delegate的已經(jīng)獲得焦點(diǎn)的方法,所以`applicationDidBecomeActive:`方法從本質(zhì)上就相當(dāng)于我們想象中的`applicationDidEnterForeground:`玖详,如果我們想要在程序進(jìn)入前臺(tái)后做什么操作把介,完全可以把這些操作寫到`applicationDidBecomeActive:`里勤讽。同理,`applicationWillResignActive:`就相當(dāng)于我們想象中的`applicationWillEnterForeground:`拗踢。
另外一般如果**應(yīng)用程序要保存用戶數(shù)據(jù)會(huì)在程序?qū)⒁ソ裹c(diǎn)的方法中進(jìn)行 (而不是在已經(jīng)進(jìn)入后臺(tái)的方法中執(zhí)行)**地技,因?yàn)槿绻脩綦p擊Home不會(huì)進(jìn)入后臺(tái)只會(huì)注銷激活。同理秒拔,如果用戶恢復(fù)應(yīng)用狀態(tài)一般在已經(jīng)獲的焦點(diǎn)的方法中執(zhí)行(而不是在將要進(jìn)入前臺(tái)的方法中執(zhí)行)。
文/VV木公子(簡書作者)
**PS:如非特別說明飒硅,所有文章均為原創(chuàng)作品砂缩,著作權(quán)歸作者所有,轉(zhuǎn)載請聯(lián)系作者獲得授權(quán)三娩,并注明出處庵芭,所有打賞均歸本人所有!**
如果您是iOS開發(fā)者雀监,或者對(duì)本篇文章感興趣双吆,請關(guān)注本人,后續(xù)會(huì)更新更多相關(guān)文章会前!敬請期待好乐!