1. 程式人生 > >iOS程序啟動原理的理解

iOS程序啟動原理的理解

ret plist 依然 默認 main oar 正常 點擊 函數

應用的生命周期(從啟動到退出):當用戶點擊應用圖標之後,應用就開始啟動。應用啟動完成後,就會展示一系列的視圖,和用戶進行各種各樣的交互(如滑動、點擊)。當用戶退出應用後,該應用就無法和用戶進行交互。這一過程就是應用的生命周期體現

在介紹應用啟動過程及原理之前,先來了解一些概念以及其作用。

1、UIApplication

UIApplication對象是應用程序的象征,一個UIApplication對象就代表一個應用程序。每一個應用都有自己的UIApplication對象,而且是單例的,如果試圖在程序中新建一個UIApplication對象,那麽將報錯提示。一個iOS

程序啟動後創建的第一個對象就是UIApplication對象,且只有一個。利用UIApplication對象,能進行一些應用級別的操作。可以參考這篇文章

2、UIApplication Delegate

所有的移動操作系統都有個致命的缺點:app很容易受到打擾。比如一個來電或者鎖屏會導致app進入後臺甚至被終止。還有很多其它類似的情況會導致app受到幹擾,在app受到幹擾時,會產生一些系統事件(iOS系統處理系統的事件的有限級別高於處理某個程序的事件),這時UIApplication會通知它的delegate對象,讓delegate代理來處理這些系統事件

所有UIApplicationDelegate的代理作用是當應用程序發出一系列系統事件時,做出相應的反應,也就是監聽應用程序的狀態變化如:進入、退出、程序間的調轉

。每次新建完項目,都有個帶有“AppDelegate”字眼的類,它就是UIApplication的代理,AppDelegate默認已經遵守了UIApplicationDelegate協議,已經是UIApplication的代理。系統事件如程序降將要啟動、程序啟動完成、程序進入後臺、程序進入前臺、程序退出等。對應代理的方法如下:

  1. /**
  2. * 程序啟動完成:各個類加載完畢
  3. */
  4. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  5. return YES;
  6. }
  7. /**
  8. * 程序將要進入後臺:還沒有進入後臺的事件點,此時用戶和界面還能夠交互
  9. */
  10. - (void)applicationWillResignActive:(UIApplication *)application {
  11. }
  12. /**
  13. * 程序進入後臺 :直觀的表現是用戶不能界面交互
  14. */
  15. - (void)applicationDidEnterBackground:(UIApplication *)application {
  16. }
  17. /**
  18. * 程序將要進入前臺
  19. */
  20. - (void)applicationWillEnterForeground:(UIApplication *)application {
  21. }
  22. /**
  23. * 程序進入前臺:獲得的焦點,用戶有能夠與界面交互
  24. */
  25. - (void)applicationDidBecomeActive:(UIApplication *)application {
  26. }
  27. /**
  28. * 程序退出:
  29. */
  30. - (void)applicationWillTerminate:(UIApplication *)application {
  31. }

上面就是涉及到應用程序非常重要的兩個概念,下面我們來介紹點擊應用圖標後,應用程序的啟動。

,C語言是從main函數開始執行代碼的。OC作為C語言的超集,當然也不例外。點擊圖標,開始執行main函數。iOS項目中的main函數是在創建項目的時候就已經寫好了的,如下:

int main(int argc, char * argv[]) {

@autoreleasepool {

return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));

}

}

  • UIApplicationMain函數參數

可以看到ios項目中的main函數執行了一個UIApplicationMain函數,所有我們的重點就是要連接UIApplicationMain在執行的時候都做了哪些事情。下面我們先來了解一下UIApplicationMain函數的參數

  1. /**
  2. * @param argc 系統參數
  3. * @param argv 系統參數
  4. * @param nil 應用程序名稱
  5. * @param class] 應用程序代理名稱
  6. */
  7. UIApplicationMain(int argc, charchar *argv[], NSString *principalClassName, NSString *delegateClassName);</span>

argc、argv:直接傳遞給UIApplicationMain進行相關處理即可

principalClassName:指定應用程序類名(app的象征),該類必須是UIApplication(或子類)。如果為nil,則用UIApplication類作為默認值

delegateClassName:指定應用程序的代理類,該類必須遵守UIApplicationDelegate協議:同過代理來監聽各種程序各種狀態的轉變

  • UIApplicationMain函數作用

main函數中之是執行了UIApplicationMain函數,可以肯定的時候該函數一定很重要,但它的具體作用是什麽呢,

UIApplicationMain函數會根據principalClassName創建UIApplication對象,根據delegateClassName創建一個delegate對象,並將該delegate對象賦值給UIApplication對象中的delegate屬性 。

接著會建立應用程序的Main Runloop(事件循環),進行事件的處理(首先會在程序完畢後調用delegate對象的application:didFinishLaunchingWithOptions:方法)。

app啟動時會加載Info.plist文件,看是否指定了main.storyboard,如果設置了就去加載main.storyboard,那麽加載main.storyboard時,系統會進行如下操作:

創建窗口 -> 加載main.storyboard並且加載main.storyboard中指定的控制器 -> 創建控制器成為窗口的根控制器,讓窗口顯示出來。

總結UIApplicationMain函數作用

argc:系統或者用戶傳入的參數 argv:系統或用戶傳入的實際參數 1.根據傳入的第三個參數,創建UIApplication對象 2.根據傳入的第四個產生創建UIApplication對象的代理 3.設置剛剛創建出來的代理對象為UIApplication的代理 4.開啟一個事件循環(可以理解為裏面是一個死循環)這個時間循環是一個隊列(先進先出)先添加進去的先處理
5.加載Info.plist文件,看是否指定了main.storyboard,如果設置了就去加載main.storyboard

3、UIWindow的創建

UIWindow 是特殊的 UIView ,通常一個App中只有UIWindows,當程序啟動完畢後,創建的第一個視圖控件就是UIWindow,接著創建控制器的UIView,將控制器的View添加到UIWindow上,控制器的 UIView 就顯示在屏幕上。註意 UIWindow 本身不做顯示,是控制器的UIView做展示,UIWindow 會給視圖分發事件。

如果應用程序設置了main.storyboard文件,並指定了初始化控制器,系統會自動創建UIWindow。如果沒有指定main.storyboard文件,就必須手動去創建。

UIWindow作用:

1.UIWindow作為一個容器,容納所有的UIView

2.UIWindow會其他事件消息傳遞給UIWiew

4、控制器的創建

當UIWindow創建完成後,必須指定一個根控制器或者在UIWIndow上添加子視圖,這樣才能顯示出來,用戶才能看得到,因為前面提到過,UIWindow本身不做顯示。當指定了UIWindow的根控制器,該控制器的view會自動添加在UIWindow上,並顯示出來。控制器的創建可以看這篇文章

5、視圖控制器view的創建

視圖控制器就是控制器視圖在屏幕上的顯示,對於一個控制器來說也是不具備顯示的,只有它的view才具有顯示能力,所以創建完一個控制器的時候,要給它指定一個根視圖。具體的控制器view的創建可以查看這篇文章。

6、應用程序的狀態

應用程序到這裏就可以顯示了。根據前面的應用程序代理功能的介紹,應用程序在啟動過程中有以下幾種狀態:

1. Not running :應用還沒有啟動,或者應用正在運行但是途中被系統停止。

2. Inactive :當前應用正在前臺運行,但是並不接收事件(當前 或許正在執行其它代碼)。一般每當應用要從一個狀態切換到另一個不同的狀態時,中途過渡會短暫停留在此狀態。唯一在此狀態停留時間比較長的情況是:當用戶 鎖屏時,或者系統提示用戶去響應某些(諸如電話來電、有未讀短信等)事件的時候。

3. Active :當前應用正在前臺運行,並且接收事件。這是應用正在前臺運行時所處的正常狀態。

4. Background :應用處在後臺,並且還在執行代碼。大多數將 要進入Suspended狀態的應用,會先短暫進入此狀態。然而,對於請求需要額外的執行時間的應用,會在此狀態保持更長一段時間。另外,如果一個應用要 求啟動時直接進入後臺運行,這樣的應用會直接從Not running狀態進入Background狀態,中途不會經過Inactive狀態。比如沒有界面的應用。註此處並不特指沒有界面的應用,其實也可以是 有界面的應用,只是如果要直接進入background狀態的話,該應用界面不會被顯示。

5. Suspended :應用處在後臺,並且已停止執行代碼。系統自動 的將應用移入此狀態,且在此舉之前不會對應用做任何通知。當處在此狀態時,應用依然駐留內存但不執行任何程序代碼。當系統發生低內存告警時,系統將會將處 於Suspended狀態的應用清除出內存以為正在前臺運行的應用提供足夠的內存。

iOS程序啟動原理的理解