app的啟動(dòng)分為pre-main()
和main()
兩個(gè)階段坦刀,本篇文章主要介紹main()
函數(shù)發(fā)生了什么圃郊。
main()函數(shù)階段
每個(gè)C語言程序都是從main()
函數(shù)開始的喳挑,Objective-C
的程序也不例外裸诽。創(chuàng)建完新的iOS工程之后浦辨,系統(tǒng)會(huì)默認(rèn)為我們創(chuàng)建一個(gè)main.m
文件蹬竖。main.m
的代碼一般如下:
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
main()
函數(shù)中只調(diào)用了一個(gè)函數(shù)UIApplicationMain()
,接下來介紹一下UIApplicationMain()
函數(shù)荤牍。
UIApplicationMain()函數(shù)
/**
創(chuàng)建application及其代理案腺,創(chuàng)建事件循環(huán)
@param argc argv中參數(shù)的數(shù)量
@param argv 參數(shù)的列表
@param principalClassName UIApplication類名或其子類名,nil默認(rèn)為UIApplication
@param delegateClassName application delegate的類名康吵,如果從nib文件加載代理劈榨,則設(shè)為nil(不太理解)
@return Never Return
*/
int UIApplicationMain(int argc, char * _Nonnull *argv, NSString *principalClassName, NSString *delegateClassName);
看一下UIApplicationMain()
的官方文檔:
This function instantiates the application object from the principal class and instantiates the delegate (if any) from the given class and sets the delegate for the application. It also sets up the main event loop, including the application’s run loop, and begins processing events. If the application’s Info.plist file specifies a main nib file to be loaded, by including the NSMainNibFile key and a valid nib file name for the value, this function loads that nib file.
Despite the declared return type, this function never returns.
由此可知,UIApplicationMain()
主要做了以下事情:
- 首先晦嵌,創(chuàng)建
UIApplication
的單例同辣。每一個(gè)iOS應(yīng)用只有一個(gè)UIApplication
對(duì)象拷姿,application主要負(fù)責(zé)用戶事件的分發(fā),它內(nèi)部維護(hù)了一個(gè)開放的window對(duì)象的列表旱函,可以通過這個(gè)列表追溯到app的任何一個(gè)view响巢。如果必須要在系統(tǒng)之前處理用戶事件,可以繼承UIApplication
并且重寫sendEvent:
和sendAction:to:from:forEvent:
方法棒妨。 - 接著踪古,根據(jù)傳入的類名創(chuàng)建代理對(duì)象(也是單例),并且設(shè)置為
UIApplication
單例的代理券腔。代理遵守UIApplicationDelegate
協(xié)議伏穆,對(duì)app的生命周期的重要事件做出響應(yīng),例如app的初始化纷纫,app狀態(tài)的切換和恢復(fù)枕扫,系統(tǒng)事件等。 - 然后辱魁,創(chuàng)建主事件循環(huán)(包含application所需要用到的run loop)烟瞧,保證程序不退出,開始處理事件染簇。
- 最后参滴,如果
info.plist
中設(shè)置了NSMainNibFile
并且對(duì)應(yīng)的值有效,則會(huì)加載對(duì)應(yīng)的nib文件锻弓。
UIApplicationDelegate
UIApplicationMain()
函數(shù)在完成上述的主要事情之后卵洗,會(huì)進(jìn)行第一次初始化,此時(shí)會(huì)回調(diào)UIApplicationDelegate
的application:willFinishLaunchingWithOptions:
方法弥咪,這是開發(fā)者能夠編寫自定義代碼的第一個(gè)地方。
接下來會(huì)恢復(fù)UI狀態(tài)十绑,然后是最終的初始化聚至,此時(shí)會(huì)回調(diào)UIApplicationDelegate
的application:didFinishLaunchingWithOptions:
方法,在這個(gè)方法中設(shè)置keyWindow
本橙,并且創(chuàng)建根控制器扳躬。
以下為新建的空工程UIApplicationDelegate
方法的執(zhí)行順序:
- 啟動(dòng)程序
2018-06-14 02:40:17.954918+0800 AppProgrammingDemo[54037:27963804] -[AppDelegate application:willFinishLaunchingWithOptions:]
2018-06-14 02:40:17.955391+0800 AppProgrammingDemo[54037:27963804] -[AppDelegate application:didFinishLaunchingWithOptions:]
2018-06-14 02:40:17.968420+0800 AppProgrammingDemo[54037:27963804] -[AppDelegate applicationDidBecomeActive:]
- 按Home鍵
2018-06-14 02:42:55.144510+0800 AppProgrammingDemo[54037:27963804] -[AppDelegate applicationWillResignActive:]
2018-06-14 02:42:55.726878+0800 AppProgrammingDemo[54037:27963804] -[AppDelegate applicationDidEnterBackground:]
- 再次點(diǎn)擊icon
2018-06-14 02:43:34.248368+0800 AppProgrammingDemo[54037:27963804] -[AppDelegate applicationWillEnterForeground:]
2018-06-14 02:43:34.533594+0800 AppProgrammingDemo[54037:27963804] -[AppDelegate applicationDidBecomeActive:]