[轉]淺論ViewController的加載 -- 解決 viewDidLoad 被提前加載的問題(pushViewController 前執行)


一個ViewController,一般通過init或initWithNibName來加載。二者沒有什么不同,init最終還是要調用initWithNibName方法(除非這個ViewController沒有nib文件)。

我們經常在initWithNibName方法中初始化視圖,變量或者其他成員。這是最常見的initWithNibName方法寫法:

- (id)initWithNibName:(NSString *)nibNameOrNilbundle:(NSBundle *)nibBundleOrNil

{

    self = [superinitWithNibName:nibNameOrNil bundle:nibBundleOrNil];

    if (self) {

        label=[[UILabelalloc]initWithFrame:

                  CGRectMake(0,0,160,160)];

        [self.viewaddSubview:label];

...

    }

    returnself;

}

在if語句中,包含了最常見的成員初始化代碼。

在這段代碼中,如果你向ViewController的視圖樹中加入一些新的UIView子類,比如上面的代碼:

[self.viewaddSubview:label];

這不會有什么問題。但是這會導致另一個方法的調用,即viewDidLoad方法。

viewDidLoad方法一般情況下只會在nib文件已載入內存(即視圖樹構建完成)之后調用。

但還有另一種情況,如果ViewController的view屬性被引用時,view=nil,也會導致nib的加載行為,從而也導致viewDidLoad方法的調用。如果你在initWithNibName方法一直不引用view屬性,則直至initWithNibName方法結束,viewDidLoad方法也不會觸發。

你也許奇怪,如果在代碼中你一直不引用這個ViewController的view屬性怎么辦?那么是不是viewDidLoad方法一直都不會調用了?

它會在ViewController對象第1次present時調用,比如你使用presentModalViewController或pushViewController方法彈出它。這兩個方法同時還會調用ViewController的appear方法(即viewWillAppear方法和viewDidAppear方法)。

viewDidLoad方法會比appear方法要早執行(appear方法會導致一個彈出動畫產生)。而且如果在present之前已經執行過viewDidLoad方法,則present方法不會觸發viewDidLoad方法。

這就是為什么我們會奇怪viewDidLoad方法中的代碼有時執行有時似乎不被執行的原因。其實根源還是在initWithNibName方法的if語句中。

如果你在initWithNibName時,引用了ViewController的view屬性,由於此時view為nil,將觸發nib文件的加載行為,導致viewDidLoad方法不等present就提前調用了。由於initWithNibName方法中ViewController成員還未初始化,導致任何對這些成員的引用都是無效的。

比如在viewDidLoad方法中,由於該方法提前執行,導致數據訪問對象還是nil(initWithNibName仍然未執行完)。如果此時在viewDidLoad方法想通過數據訪問對象獲取表格數據,將得到空。這樣從表面上看,viewDidLoad方法似乎未被執行。

這個情況可以通過兩種方法來改進:

一、initWithNibName方法中,不要有任何成員初始化的代碼。把這些代碼移到viewDidLoad方法開始進行。

二、由於initWithNibName方法保證是在present方法中進行,我們也可以在initWithNibName方法中保留成員初始化代碼。但把原來viewDidLoad方法中的代碼移到appear方法中。也就是,最好不要在viewDidLoad方法中進行和成員初始化無關的事情。這樣還有一個好處,每次presentViewController,都會執行appear方法中的代碼(如果是viewDidLoad方法,則只會在加載nib時執行)。


loadview也是第1次引用ViewController的view屬性(此時,view=nil)時調用,但在viewDidLoad之前。不同的是,loadview在view樹構建前調用,viewDidLoad在view樹構建完成后調用。二者之間,則進行nib的加載。因此,我們常在編程方式創建viewcontroller時重載loadview方法,因為本來就不需要加載nib的內容。

 

轉:http://blog.sina.com.cn/s/blog_947c4a9f01015i23.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM