當(dāng)用戶點(diǎn)擊應(yīng)用圖標(biāo)之后,應(yīng)用就開(kāi)始啟動(dòng)。應(yīng)用啟動(dòng)完成后,就會(huì)展示一系列的視圖,和用戶進(jìn)行各種各樣的交互(如滑動(dòng)、點(diǎn)擊)。當(dāng)用戶退出應(yīng)用后,該應(yīng)用就無(wú)法和用戶進(jìn)行交互。這一過(guò)程就體現(xiàn)了一個(gè)應(yīng)用的生命周期(從啟動(dòng)到退出)。這里只介紹應(yīng)用程序的顯示部分。
在介紹應(yīng)用啟動(dòng)過(guò)程及原理之前,先來(lái)了解一些概念以及其作用。
1、UIApplication
UIApplication對(duì)象是應(yīng)用程序的象征,一個(gè)UIApplication對(duì)象就代表一個(gè)應(yīng)用程序。每一個(gè)應(yīng)用都有自己的UIApplication對(duì)象,而且是單例的,如果試圖在程序中新建一個(gè)UIApplication對(duì)象,那么將報(bào)錯(cuò)提示。一個(gè)iOS程序啟動(dòng)后創(chuàng)建的第一個(gè)對(duì)象就是UIApplication對(duì)象,且只有一個(gè)。利用UIApplication對(duì)象,能進(jìn)行一些應(yīng)用級(jí)別的操作。可以參考[[iOS開(kāi)發(fā)之UIApplication和delegate](http://blog.csdn.net/shxwork/article/details/50053489)](http://blog.csdn.net/shxwork/article/details/50053489)
2、UIApplication Delegate
所有的移動(dòng)操作系統(tǒng)都有個(gè)問(wèn)題:APP很容易受到打擾。比如來(lái)電或者鎖屏?xí)?dǎo)致APP進(jìn)入后臺(tái)甚至被終止。還有很多其它類似的情況會(huì)導(dǎo)致app受到干擾,在app受到干擾時(shí),會(huì)產(chǎn)生一些系統(tǒng)事件,這時(shí)UIApplication會(huì)通知它的delegate對(duì)象,讓delegate代理來(lái)處理這些系統(tǒng)事件。
UIApplication Delegate的作用是當(dāng)應(yīng)用程序發(fā)出一系列系統(tǒng)事件時(shí),做出相應(yīng)的反應(yīng)。新建完項(xiàng)目,都有個(gè)帶有“AppDelegate”字眼的類,它就是UIApplication的代理,AppDelegate默認(rèn)已經(jīng)遵守了UIApplicationDelegate協(xié)議,已經(jīng)是UIApplication的代理。系統(tǒng)事件如程序降將要啟動(dòng)、程序啟動(dòng)完成、程序進(jìn)入后臺(tái)、程序進(jìn)入前臺(tái)、程序退出等。對(duì)應(yīng)代理的方法如下:
/**
* 程序啟動(dòng)完成
*/
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
return YES;
}
/**
* 程序?qū)⒁M(jìn)入后臺(tái)
*/
- (void)applicationWillResignActive:(UIApplication *)application
{ }
/**
* 程序進(jìn)入后臺(tái)
*/
- (void)applicationDidEnterBackground:(UIApplication *)application
{ }
/**
* 程序?qū)⒁M(jìn)入前臺(tái)
*/
- (void)applicationWillEnterForeground:(UIApplication *)application
{ }
/**
* 程序進(jìn)入前臺(tái)
*/
- (void)applicationDidBecomeActive:(UIApplication *)application
{ }
/**
* 程序退出
*/
- (void)applicationWillTerminate:(UIApplication *)application
{ }
上面就是涉及到應(yīng)用程序非常重要的兩個(gè)概念,下面我們來(lái)介紹點(diǎn)擊應(yīng)用圖標(biāo)后,應(yīng)用程序的啟動(dòng)。我們都知道,C語(yǔ)言是從main函數(shù)開(kāi)始執(zhí)行代碼的。OC作為C語(yǔ)言的超集,當(dāng)然也不例外。點(diǎn)擊圖標(biāo),開(kāi)始執(zhí)行main函數(shù)。iOS項(xiàng)目中的main函數(shù)是在創(chuàng)建項(xiàng)目的時(shí)候就已經(jīng)寫好了的,如下:
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
UIApplicationMain函數(shù)參數(shù)
可以看到iOS項(xiàng)目中的main函數(shù)執(zhí)行了一個(gè)UIApplicationMain函數(shù),所有我們的重點(diǎn)就是要連接UIApplicationMain在執(zhí)行的時(shí)候都做了哪些事情。下面我們先來(lái)了解一下UIApplicationMain函數(shù)的參數(shù)
* @param argc 系統(tǒng)參數(shù)
* @param argv 系統(tǒng)參數(shù)
* @param nil 應(yīng)用程序名稱
* @param class] 應(yīng)用程序代理名稱
*/
UIApplicationMain(int argc, charchar *argv[], NSString *principalClassName, NSString *delegateClassName);
argc、argv:直接傳遞給UIApplicationMain進(jìn)行相關(guān)處理即可
principalClassName:指定應(yīng)用程序類名(app的象征),該類必須是UIApplication(或子類)。如果為nil,則用UIApplication類作為默認(rèn)值
delegateClassName:指定應(yīng)用程序的代理類,該類必須遵守UIApplicationDelegate協(xié)議
UIApplicationMain函數(shù)作用
main函數(shù)中之是執(zhí)行了UIApplicationMain函數(shù),可以肯定的時(shí)候該函數(shù)一定很重要,但它的具體作用是什么呢,
UIApplicationMain函數(shù)會(huì)根據(jù)principalClassName創(chuàng)建UIApplication對(duì)象,根據(jù)delegateClassName創(chuàng)建一個(gè)delegate對(duì)象,并將該delegate對(duì)象賦值給UIApplication對(duì)象中的delegate屬性 。
接著會(huì)建立應(yīng)用程序的Main Runloop(事件循環(huán)),進(jìn)行事件的處理(首先會(huì)在程序完畢后調(diào)用delegate對(duì)象的application:didFinishLaunchingWithOptions:方法)。
app啟動(dòng)時(shí)會(huì)加載Info.plist文件,看是否指定了main.storyboard,如果設(shè)置了就去加載main.storyboard,那么加載main.storyboard時(shí),系統(tǒng)會(huì)進(jìn)行如下操作:
創(chuàng)建窗口 -> 加載main.storyboard并且加載main.storyboard中指定的控制器 -> 創(chuàng)建控制器成為窗口的根控制器,讓窗口顯示出來(lái)。
總結(jié)UIApplicationMain函數(shù)作用:
argc:系統(tǒng)或者用戶傳入的參數(shù)
argv:系統(tǒng)或用戶傳入的實(shí)際參數(shù)
1.根據(jù)傳入的第三個(gè)參數(shù),創(chuàng)建UIApplication對(duì)象
2.根據(jù)傳入的第四個(gè)產(chǎn)生創(chuàng)建UIApplication對(duì)象的代理
3.設(shè)置剛剛創(chuàng)建出來(lái)的代理對(duì)象為UIApplication的代理
4.開(kāi)啟一個(gè)事件循環(huán)(可以理解為里面是一個(gè)死循環(huán))這個(gè)時(shí)間循環(huán)是一個(gè)隊(duì)列(先進(jìn)先出)先添加進(jìn)去的先處理
5.加載Info.plist文件,看是否指定了main.storyboard,如果設(shè)置了就去加載main.storyboard
3、UIWindow的創(chuàng)建
UIWindow 是特殊的 UIView ,通常一個(gè)App中只有UIWindows,當(dāng)程序啟動(dòng)完畢后,創(chuàng)建的第一個(gè)視圖控件就是UIWindow,接著創(chuàng)建控制器的UIView,將控制器的View添加到UIWindow上,控制器的 UIView 就顯示在屏幕上。注意 UIWindow 本身不做顯示,是控制器的UIView做展示,UIWindow 會(huì)給視圖分發(fā)事件。
如果應(yīng)用程序設(shè)置了main.storyboard文件,并指定了初始化控制器,系統(tǒng)會(huì)自動(dòng)創(chuàng)建UIWindow。如果沒(méi)有指定main.storyboard文件,就必須手動(dòng)去創(chuàng)建。
UIWindow作用:
1.UIWindow作為一個(gè)容器,容納所有的UIView
2.UIWindow會(huì)其他事件消息傳遞給UIWiew
4、控制器的創(chuàng)建
當(dāng)UIWindow創(chuàng)建完成后,必須指定一個(gè)根控制器或者在UIWIndow上添加子視圖,這樣才能顯示出來(lái),用戶才能看得到,因?yàn)榍懊嫣岬竭^(guò),UIWindow本身不做顯示。當(dāng)指定了UIWindow的根控制器,該控制器的view會(huì)自動(dòng)添加在UIWindow上,并顯示出來(lái)??刂破鞯膭?chuàng)建可以看[這篇文章](http://blog.csdn.net/shxwork/article/details/50060645)
5、視圖控制器view的創(chuàng)建
視圖控制器就是控制器視圖在屏幕上的顯示,對(duì)于一個(gè)控制器來(lái)說(shuō)也是不具備顯示的,只有它的view才具有顯示能力,所以創(chuàng)建完一個(gè)控制器的時(shí)候,要給它指定一個(gè)根視圖。具體的控制器view的創(chuàng)建可以查看[這篇文章](http://blog.csdn.net/shxwork/article/details/50065917)。
6、應(yīng)用程序的狀態(tài)
應(yīng)用程序到這里就可以顯示了。根據(jù)前面的應(yīng)用程序代理功能的介紹,應(yīng)用程序在啟動(dòng)過(guò)程中有以下幾種狀態(tài):
- Not running :應(yīng)用還沒(méi)有啟動(dòng),或者應(yīng)用正在運(yùn)行但是途中被系統(tǒng)停止。
- Inactive :當(dāng)前應(yīng)用正在前臺(tái)運(yùn)行,但是并不接收事件(當(dāng)前 或許正在執(zhí)行其它代碼)。一般每當(dāng)應(yīng)用要從一個(gè)狀態(tài)切換到另一個(gè)不同的狀態(tài)時(shí),中途過(guò)渡會(huì)短暫停留在此狀態(tài)。唯一在此狀態(tài)停留時(shí)間比較長(zhǎng)的情況是:當(dāng)用戶 鎖屏?xí)r,或者系統(tǒng)提示用戶去響應(yīng)某些(諸如電話來(lái)電、有未讀短信等)事件的時(shí)候。
- Active :當(dāng)前應(yīng)用正在前臺(tái)運(yùn)行,并且接收事件。這是應(yīng)用正在前臺(tái)運(yùn)行時(shí)所處的正常狀態(tài)。
- Background :應(yīng)用處在后臺(tái),并且還在執(zhí)行代碼。大多數(shù)將 要進(jìn)入Suspended狀態(tài)的應(yīng)用,會(huì)先短暫進(jìn)入此狀態(tài)。然而,對(duì)于請(qǐng)求需要額外的執(zhí)行時(shí)間的應(yīng)用,會(huì)在此狀態(tài)保持更長(zhǎng)一段時(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)過(guò)Inactive狀態(tài)。比如沒(méi)有界面的應(yīng)用。注此處并不特指沒(méi)有界面的應(yīng)用,其實(shí)也可以是 有界面的應(yīng)用,只是如果要直接進(jìn)入background狀態(tài)的話,該應(yīng)用界面不會(huì)被顯示。
- Suspended :應(yīng)用處在后臺(tái),并且已停止執(zhí)行代碼。系統(tǒng)自動(dòng) 的將應(yīng)用移入此狀態(tài),且在此舉之前不會(huì)對(duì)應(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)存。
