一:App的不同狀態(tài)
對于iOS app 來說弄痹,知道app當(dāng)前的狀態(tài)是至關(guān)重要的悍及,因?yàn)閕OS對系統(tǒng)資源有著相當(dāng)嚴(yán)格的限制安券,app 在不同的狀態(tài)下可執(zhí)行的操作也是不同的悉盆。在當(dāng)程序處于后臺(tái)時(shí),系統(tǒng)對app所能執(zhí)行的操作做了嚴(yán)格的限制典唇,以提高電池的使用時(shí)間和正在運(yùn)行程序的用戶體驗(yàn)镊折。當(dāng)在前后臺(tái)切換app時(shí),系統(tǒng)會(huì)發(fā)出相應(yīng)的通知蚓聘,在這些通知中可以改變app的操作。
當(dāng)你實(shí)現(xiàn)程序代碼時(shí)盟劫,應(yīng)該遵循下面這些建議:
1.(必須)當(dāng)發(fā)生狀態(tài)轉(zhuǎn)換時(shí)進(jìn)行恰當(dāng)?shù)捻憫?yīng)處理夜牡,如果不進(jìn)行處理操作可能會(huì)導(dǎo)致數(shù)據(jù)的丟失和不好的用戶體驗(yàn)。(具體參考一下 1的內(nèi)容)
2.(必須)當(dāng)app轉(zhuǎn)入后臺(tái)時(shí)侣签,確保app所執(zhí)行的操作是正確地被循序的操作(后臺(tái)允許5中操作塘装,詳細(xì)見下面)
3.(建議)注冊任何你需要的報(bào)告系統(tǒng)發(fā)生改變的通知。當(dāng)app被掛起時(shí)影所,系統(tǒng)會(huì)把重要的通知放入隊(duì)列蹦肴,當(dāng)再次執(zhí)行時(shí)再分配這些通知,app應(yīng)該使用這些通知來實(shí)現(xiàn)流暢的從后臺(tái)到前臺(tái)的轉(zhuǎn)化猴娩。
app的幾種狀態(tài):
not running:沒有啟動(dòng)或啟動(dòng)后被系統(tǒng)結(jié)束阴幌。
Inactive:系統(tǒng)在前臺(tái)執(zhí)行但不接受任何的操作和處理,app一般短暫的處于這個(gè)狀態(tài)然后轉(zhuǎn)向別的狀態(tài)卷中。唯一在此狀態(tài)停留時(shí)間比較長的情況是:當(dāng)用戶鎖屏?xí)r矛双,或者系統(tǒng)提示用戶去響應(yīng)某些(諸如電話來電、有未讀短信等)事件的時(shí)候蟆豫。
Active:app在前臺(tái)執(zhí)行并且接受操作议忽,這是前臺(tái)app的一般狀態(tài)。
Background:app進(jìn)入后臺(tái)并且還在執(zhí)行代碼十减。大多數(shù)將要進(jìn)入Suspended狀態(tài)的應(yīng)用栈幸,會(huì)先短暫進(jìn)入此狀態(tài)。然而帮辟,對于請求額外的執(zhí)行時(shí)間的應(yīng)用速址,會(huì)在此狀態(tài)保持更長一段時(shí)間。另外由驹,如果一個(gè)應(yīng)用要求啟動(dòng)時(shí)直接進(jìn)入后臺(tái)運(yùn)行壳繁,這樣的應(yīng)用會(huì)直接從Not running狀態(tài)進(jìn)入Background狀態(tài),中途不會(huì)經(jīng)過Inactive狀態(tài)。比如沒有界面的應(yīng)用闹炉。注此處并不特指沒有界面的應(yīng)用蒿赢,其實(shí)也可以是有界面的應(yīng)用,只是如果要直接進(jìn)入background狀態(tài)的話渣触,該應(yīng)用界面不會(huì)被顯示羡棵。
Suspended:app在后臺(tái),并且已停止執(zhí)行代碼嗅钻。系統(tǒng)自動(dòng)的將應(yīng)用移入此狀態(tài)皂冰,且在此舉之前不會(huì)對應(yīng)用做任何通知。當(dāng)處在此狀態(tài)時(shí)养篓,應(yīng)用依然駐留內(nèi)存但不執(zhí)行任何程序代碼秃流。當(dāng)系統(tǒng)發(fā)生低內(nèi)存告警時(shí),系統(tǒng)將會(huì)將處于Suspended狀態(tài)的應(yīng)用清除出內(nèi)存為正在前臺(tái)運(yùn)行的應(yīng)用提供足夠的內(nèi)存柳弄。
當(dāng)app發(fā)生狀態(tài)變化時(shí)都伴隨著程序代理函數(shù)的調(diào)用舶胀,這些方法調(diào)用就是我們響應(yīng)程序狀態(tài)改變的最佳時(shí)機(jī)。
application:willFinishLaunchingWithOptions: 即將啟動(dòng)時(shí)調(diào)用
application:didFinishLaunchingWithOptions:這些代碼允許你在程序顯示給用戶之前執(zhí)行一些最后的初始化工作
applicationDidBecomeActive: app成為前臺(tái)運(yùn)行程序時(shí)調(diào)用
applicationWillResignActive:你的程序正過渡遠(yuǎn)離作為前臺(tái)應(yīng)用程序碧注。使用此方法來把你的應(yīng)用程序在一個(gè)靜止的狀態(tài)嚣伐。
applicationDidEnterBackground:app 進(jìn)入后臺(tái)運(yùn)行,并且隨時(shí)可能被掛起
applicationWillEnterForeground:app 即將作為前臺(tái)程序運(yùn)行程序萍丐。
applicationWillTerminate:app 當(dāng)前應(yīng)用即將被終止轩端,在終止前調(diào)用的函數(shù)。如果應(yīng)用當(dāng)前處在suspended逝变,此方法不會(huì)被調(diào)用基茵。
常見的狀態(tài)轉(zhuǎn)換:
狀態(tài)之間是可以相互轉(zhuǎn)換的,下面簡述幾種常見的方式壳影。
當(dāng)一個(gè) App 在非運(yùn)行狀態(tài)時(shí)耿导,用戶可以通過點(diǎn)擊 App 的 Icon 或者 App 的通知來打開一個(gè) App。
需要注意的是态贤,即使 silent 通知舱呻,在這種狀態(tài)下也是無法喚醒 App 的。
然后 App 進(jìn)入到活躍狀態(tài)悠汽。當(dāng)用戶在使用 App 的過程中箱吕,會(huì)發(fā)生一些事件,然后 App 會(huì)進(jìn)入非活躍狀態(tài)柿冲。比如:
收到一條短信茬高、來電時(shí)。
收到一個(gè)到期的提醒事項(xiàng)時(shí)假抄。
收到一個(gè)通知怎栽,并且該通知是屬于那種彈出模式時(shí)丽猬。
用戶雙擊 Home 鍵,進(jìn)入到 App 切換界面熏瞄。
用戶一般不會(huì)在這個(gè)狀態(tài)下停留很久的時(shí)間脚祟,當(dāng)阻礙 App 成為用戶第一焦點(diǎn)的其他消失或被用戶處理后,App 馬上恢復(fù)到活躍狀態(tài)强饮。
用戶摁下 Home 鍵或者切換到別的 App 時(shí)由桌,App 將進(jìn)入到后臺(tái)運(yùn)行狀態(tài),在這種狀態(tài)下邮丰,只能在有限的時(shí)間內(nèi)做一些簡單的工作行您,然后 App 將會(huì)休眠,進(jìn)入到暫停狀態(tài)剪廉。
在暫停狀態(tài)下娃循,App 是什么都干不了的,只能等待用戶主動(dòng)喚醒或者 silent 通知斗蒋。
休眠的 App 在收到 silent 通知時(shí)捌斧,將會(huì)進(jìn)入后臺(tái)狀態(tài),又可以在有限的時(shí)間內(nèi)做一些工作吹泡。
如果使用新聞?lì)?App ,或者系統(tǒng)的郵箱服務(wù)時(shí),可以發(fā)現(xiàn),有時(shí)候 App 明明沒有被打開過,但是在打開時(shí),內(nèi)容已經(jīng)做了更新骤星。
這里就用到了 silent 推送经瓷,App 接收到 silent 推送然后進(jìn)入后臺(tái)運(yùn)行模式爆哑,做網(wǎng)絡(luò)請求,得到數(shù)據(jù)舆吮,然后更新 model揭朝。這樣子用戶在下次打開 App 時(shí),將會(huì)看到已經(jīng)更新好的數(shù)據(jù)色冀,而不是再去做網(wǎng)絡(luò)請求潭袱,這樣子很好的提升了用戶體驗(yàn)。
當(dāng) App 在休眠狀態(tài)太久锋恬,并且更多的 App 進(jìn)入到休眠狀態(tài)時(shí)屯换,系統(tǒng)的內(nèi)容將不夠用,因?yàn)?App 在休眠時(shí)与学,為了能夠快速的將其激活彤悔,是將其放在內(nèi)存中的。
這樣子索守,用戶就感覺好像使用的 App 沒有被關(guān)閉晕窑,一直在運(yùn)行。
內(nèi)存不夠用時(shí)卵佛,休眠時(shí)間比較長的 App 會(huì)被清退出內(nèi)存杨赤,進(jìn)入到非運(yùn)行狀態(tài)敞斋。
二、關(guān)于main函數(shù)疾牲,UIApplication類和UIApplication代理類
每一個(gè)iPhone程序都包含一個(gè)UIApplication對象,它管理整個(gè)程序的生命周期,從加載第一個(gè)顯示界面開始植捎,并且監(jiān)聽系統(tǒng)事件、程序事件 说敏、調(diào)度整個(gè)程序的執(zhí)行鸥跟。
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
這句代碼UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]))的作用是:初始化一個(gè)UIApplication對象。這個(gè)對象是隱含的盔沫,這個(gè)方法除了argc 和 argv 系統(tǒng)傳入的參數(shù)外医咨,還有兩個(gè)字符串參數(shù)用來識(shí)別UIApplication類和UIApplication代理類。在這里第一個(gè)參數(shù)為nil就默認(rèn)把UIApplication類作為缺省值進(jìn)行初始化架诞,也可以不填nil而是使用自定義的UIApplication子類拟淮。至于第二個(gè)參數(shù),這里有了UIApplication對象怎么又出來一個(gè)UIApplication代理類對象呢谴忧?這里需要說明UIApplication對象說是管理整個(gè)程序的生命周期的很泊,其實(shí)它是什么具體的事情都不干,它只負(fù)責(zé)監(jiān)聽事件當(dāng)需要做實(shí)際工作的時(shí)候就交給UIApplication代理類去做沾谓,UIApplication相當(dāng)于傳令官負(fù)責(zé)只把命令傳達(dá)給UIApplication代理類這個(gè)士兵委造,然后由這個(gè)士兵真正去沖鋒陷陣,所以需要給UIApplication對象設(shè)置代理類。