對應用程式啟動時所有方法的調用順序分析,調用順序

來源:互聯網
上載者:User

對應用程式啟動時所有方法的調用順序分析,調用順序

一個應用程式的啟動過程要包括代理的建立,控制器的載入和控制器view的載入,這其中有很多關於生命週期的方法,每個方法都是有先後順序的,如果調用順序拿不準,或者某段代碼寫的方法不恰當,就會遇到各種奇葩問題。本文不怕麻煩的在幾乎所有啟動時要調用的方法裡都用了 __FUNCTION__ 列印。結果還有有些地方出人意料的

如果你不是在董鉑然部落格園看到本文,請點擊查看原文

首先回顧一下應用程式的啟動過程

①.先載入Main函數

②.在Main函數裡的 UIApplicationMain方法中,建立Application對象 建立Application的Delegate對象

③.建立主迴圈,代理對象開始監聽事件

④.啟動完畢會調用 didFinishLaunching方法,並在這個方法中建立UIWindow

⑤.設定UIWindow的根控制器是誰

⑥.如果有storyboard,會根據info.plist中找到應用程式的入口storyboard並載入箭頭所指的控制器

⑦.顯示視窗

 

本文考慮的時步驟3之後到步驟7結束時將要調用的方法

其中有AppDelegate,ViewController,MainView(控制器的View),ChildView(子控制項的View)的18個方法

AppDelegate中的:

1.application:didFinishLaunchingWithOptions:

2.applicationDidBecomeActive:

 

ViewController中的:

3.loadView

4.viewDidLoad

5.load

6.initialize

7.viewWillAppear

8.viewWillLayoutSubviews

9.viewDidLayoutSubviews

10.viewDidAppear

 

MainView(控制器的View)中的:

11.initWithCoder(如果沒有storyboard就會調用initWithFrame,這裡兩種方法視為一種)

12.awakeFromNib

13.layoutSubviews

14.drawRect

 

ChildView(子控制項View)中的:

15.initWithCoder(如果沒有storyboard就會調用initWithFrame,這裡兩種方法視為一種)

16.awakeFromNib

17.layoutSubviews

18.drawRect

 

那麼問題來了,不往下看你可以把上面的十八個方法排個順序嗎?

 

 

下面的圖是Xcode6.3的beta2版  

有時有變化也就是最後兩個方法有點出入

 

我更傾向於Xcode 6.1 覺得更科學 下面就是對各個方法的整理

 

+ (void)load;

 1.這是應用程式啟動就會調用的方法,在這個方法裡寫的代碼最先調用(董鉑然原創)

 

+ (void)initialize;

 2.這個是需要用到本類時才調用,這個方法裡一般寫 設定導航控制器的主題啊 之類的,如果在後面的方法設定導覽列主題就晚了!(當然在上面的方法裡也能寫)

 

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;

3.這個方法裡面會建立UIWindow,設定根控制器並展現,比如某些應用程式要載入授權頁面也是在這加,也可以設定觀察者,監聽到通知切換根控制器

 

ChildView - (instancetype)initWithCoder:(NSCoder *)aDecoder; 

4.這裡反正我是萬萬沒想到,childView的initwithcoder會在MainView的方法之前調用,父的都還沒出來,就先整子控制項? 有瞭解比較透徹的博友懇請告訴我謝謝。

 

MainView - (instancetype)initWithCoder:(NSCoder *)aDecoder;

5.就是關於應用程式的資料存放區後的解檔操作。

 

MainView - (void)awakeFromNib;

6.在這個方法裡設定view的背景等一系列普通操作,不要寫關於frame的還不準,在使用IB的時候才會涉及到此方法的使用,當.nib檔案被載入的時候,會發送一個awakeFromNib的訊息到.nib檔案中的每個對象,每個對象都可以定義自己的awakeFromNib函數來響應這個訊息,執行一些必要的操作。 

 

ChildView - (void)awakeFromNib

7.子控制項也有本方法,重寫父類的方法。基本用法同上 

 

- (void)loadView;

 8.建立視圖的階層,這裡需要注意,在沒有建立控制器的view的情況下不能直接寫 self.view 因為self.view的底層是:

if(_view == nil){

  _view = [self loadView]

}

所以這麼寫會直接造成死迴圈。

如果重寫這個loadView方法裡面什麼都不寫,會顯示黑屏。

如果寫了[super view]還要看前面的控制器在建立時是寫的initWithNibName(指定了xib名字),還是寫的普通的init。 如果是後者還是黑屏。

如果不在這個方法中,init的底層是會調用initWithNibName的,如果名字是MainViewController,會先在項目中找MainView.xib 找不到會再找MainViewController.xib。 

 

- (void)viewDidLoad;

9.臥槽,這個方法是當年用的最多的方法,但是在之後的開發中就會發現越來越不靠譜,很多東西都還沒載入完畢,各種取值都不準確,很少在這裡面寫東西了。 這裡只是把視圖元件載入完成,還沒有開始布局不要設定關於 frame 之類的屬性!有時可能會出現差20個像素點等狀況。

 

- (void)viewWillAppear:(BOOL)animated;

10.視圖將要出現,這個方法用的非常多,比如如果要設定導覽列的setNavigationBarHiden:animate: 就必須要在這裡寫,才能完美契合,不卡跳。 還有很多比如監聽旋轉螢幕啦,

viewWillTransitionToSize:可能要在本方法裡再調一次,或者就是新到這個介面要reloadData或是自動下拉重新整理等 都是寫在本方法裡。

 

- (void)viewWillLayoutSubviews;

11.視圖將要布局子視圖,蘋果建議的設定介面布局屬性的方法,這個方法和viewWillAppear裡,系統的底層都是沒有寫任何代碼的,也就是說這裡面不寫super 也是可以的

 

MainView  - (void)layoutSubviews;

12.在這個方法裡一般設定子控制項的frame,因為這裡相當於是布局基本完成了,設定時取到的frame或者是self.bounds才最准,如果在awakeFromeNib裡寫會不準確 。還有這裡要切記千萬不能把super layoutSubviews忘了,可能最後都很難找到這個bug

 

- (void)viewDidLayoutSubviews;

13.這個方法我也是玩玩沒想到,控制器的view的子控制項還沒有布局好呢,怎麼這個控制器就已經說布局全部完成了?那後邊的布局就不等了? 有獨到見解的也懇請你告訴我,這其中蘋果的意思到底是什麼。 

 

ChildView - (void)layoutSubviews;

14.控制器的子控制項裡的子控制項的布局就在這裡寫了。 

 

MainView - (void)drawRect:(CGRect)rect;

15. 因為預設所有額UI控制項都是畫上去的,在這一步就是把所有的東西畫上去,有時候需要用到Quartz2D的知識的時候都是在這個方法裡話,但也是要注意別忘了寫super,不然系統原本的東西就都畫不上來了,這裡要建議儘可能使用貝塞爾路徑畫圖形,因為系統預設的那個上下文畫法有時可能會記憶體泄露。drawRect方法只能在載入時調用一次,如果後面還需要調用,比如下載進度的圓弧,需要一直刷幀,就要使用setNeedsDisplay來定時多次調用本方法

 

ChildView - (void)drawRect:(CGRect)rect;

16.view的子控制項內部的畫圖方法,有時可以自己自訂label 中間帶個刪除線的(用來寫打折前的原價) 就是在這裡畫根線 。

 

- (void)viewDidAppear:(BOOL)animated;

17.把上面的畫圖都畫完了,這裡就會顯示視圖完全載入完成了。在這裡的操作可能就是設定頁面的一些動畫,或者是設定tableView,collectionView,QQ聊天頁面啥的滾動到底部scrollToIndexPath之類的代碼操作。

 

- (void)applicationDidBecomeActive:(UIApplication *)application;

 18.最後這是AppDelegate的應用程式擷取焦點方法,真正到了這裡,才是所有東西全部載入完畢,應用程式整裝待發保持最佳狀態等待使用者操作。這個方法中一班會寫關於彈出鍵盤的方法,比如有的使用者登入介面為了更好的使用者體驗,就讓你在剛開啟程式來到登入介面的時候,游標的焦點就自動在帳號的文字框裡閃爍,也就是設定帳號文字框為第一響應者。鍵盤在頁面載入完畢後從下方彈出,這種代碼一般就在本方法寫。

 

如果你不是在董鉑然部落格園看到本文,請點擊查看原文

以上總結,有不同意見的歡迎交流,歡迎關注 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.