2011-06-10 32 views
8

這是我的理解,awakeFromNib將始終在viewDidLoad之前調用。viewDidLoad and awakeFromNib timing

所以我有一個UITableViewController的子類,它從xib文件中取消存檔。

我這兩種方法定義裏面:

- (void)awakeFromNib { 
    [super awakeFromNib]; 
    NSLog(@"awake from nib"); 
} 

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    NSLog(@"view did load"); 
} 

發生的事情是在控制檯「視圖做負載」之前「從筆尖清醒」顯示出來。我試圖在[super awakeFromNib]中使用一個斷點,然後反覆點擊F7(Step Into),令我驚訝的是,在進入awakeFromNib中的第二行之前,它進入了 - (void)viewDidLoad。

有沒有人有線索這裏發生了什麼?我在普通UIViewController的子類中做了完全相同的事情,並且日誌語句被顛倒過來,正如我最初的預期的那樣...

回答

11

爲了理解這個事實,我建議你看看loadNibNamed:owner:options:方法NSBundle

當您從nib初始化視圖控制器時,首先它會加載包含在其中的視圖,然後根據nib設置文件所有者屬性。當它將文件所有者的view屬性設置爲加載的視圖之一時,將調用方法viewDidLoad。當設置了所有文件所有者的網點和屬性時(包括view屬性),將調用awakeFromNib。所以有意義的是viewDidLoad早於awakeFromNib

希望這會幫助

+2

我不確定你是對的。看看這個:http://stackoverflow.com/questions/377202/which-should-i-use-awakefromnib-or-viewdidload – Idan 2011-06-10 08:21:34

+0

那麼,我在說什麼衝突?事實是,當內存警告發生時,視圖控制器視圖(如果它不可見)被設置爲零並釋放。當它再次變得可見時,視圖控制器從它的xib文件加載其視圖並設置'self.view = viewLoadedFromXib',這樣viewDidLoad再次被調用,而不再次配置自己時不會再次調用awakeFromNib。 – Zapko 2011-06-10 08:38:52

+0

如果你不相信我或我沒有寫清楚,你可以檢查[文檔](http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/BasicViewControllers/BasicViewControllers.html%23// apple_ref/doc/uid/TP40007457-CH101-SW19)。無論如何,它會更有用。 – Zapko 2011-06-10 09:01:23

5

我不認爲你必須在你的超類上調用awakeFromNib。

檢查this

編輯

我只是跑了一個快速測試,這裏的結果:

方案1: MainWindow.xib中有一個UIViewController子類TestingAwakeFromNibViewController,其中有它自己的NIB文件TestingAwakeFromNibViewController.xib

TestingAwakeFromNibViewController有一個名爲btn3的UIButton插座。 測試下面的代碼:

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    NSLog(@"Btn3 %@",btn3); 

    NSLog(@"viewDidLoad"); 
} 


-(void) awakeFromNib 
{ 
    [super awakeFromNib]; 

    NSLog(@"Btn3 %@",btn3); 

    NSLog(@"awakeFromNib"); 
} 

將打印:

Btn3 (null) 
AwakeFromNib 
Btn3 <UIRoundedRectButton: 0x64088e0; frame = (114 211; 72 37); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x6408890>> 
ViewDidLoad 

方案2: 刪除廈門國際銀行文件,添加一個UIView作爲一個兒子裏面的MainWindow.xib的TestingAwakeFromNibViewController,並添加UIButton作爲UIView的子視圖(並將UIbutton插座連接到TestingAwakeFromNibViewController的相應插座)。

現在運行上面的代碼將打印:

Btn3 <UIRoundedRectButton: 0x4e31c30; frame = (114 211; 72 37); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x4e31be0>> 
viewDidLoad 
Btn3 <UIRoundedRectButton: 0x4e31c30; frame = (114 211; 72 37); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x4e31be0>> 
awakeFromNib 

含義的viewDidLoad之前AwakeFromNib。

第三種情況: 相同第二,只是不調用[super awakeFromNib];

Btn3 <UIRoundedRectButton: 0x4e0ddf0; frame = (114 211; 72 37); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x4e0dda0>> 
awakeFromNib 

現在,viewDidLoad中甚至沒有得到調用。

因此,看起來不同的場景需要採取不同的行動,我們需要根據我們正在採取的行動做好準備。

+0

有趣。如果未調用[super awakeFromNib],則根本不調用viewDidLoad。所以這一切,[super awakeFromNib]調用viewDidload? – 2012-06-06 13:14:06

4

我創建基於導航的應用程序選項的測試項目,並添加以下代碼rootViewController.m。

- (void)awakeFromNib { 
    NSLog(@"awakeFromNib 1"); 
    [super awakeFromNib]; 
    NSLog(@"awakeFromNib 2"); 
} 

- (void)viewDidLoad { 
    NSLog(@"viewDidLoad 1"); 
    [super viewDidLoad]; 
    NSLog(@"viewDidLoad 2"); 
} 

然後,我從控制檯的結果:加載控制器的視圖時

awakeFromNib 1 
awakeFromNib 2 
viewDidLoad 1 
viewDidLoad 2 

-(void)viewDidLoad將被調用。所以,當您第一次使用self.view = ...時,-(void)viewDidLoad將被調用。

如果你寫了類似下面的內容,那麼將首先調用 - (void)viewDidLoad。

- (void)awakeFromNib { 
     /// viewDidLoad will be called 
     /// because self.view must be loaded first. 
     self.view.backgroundColor = [UIColor clearColor]; 
     [super awakeFromNib]; 
     NSLog(@"awakeFromNib 2"); 
    } 
+0

很好的回答,謝謝:) – evya 2016-07-25 12:30:53

0

而不被專家,並且在這之後發貼,予實現比在選項卡控制器的情況下,在「子」視圖控制器,選項卡控制器(父)在加載時執行awakeFromNib方法,但viewDidLoad中只有當它的「Tab」被點擊時。

而且,因此我明白,只有在選擇特定選項卡時才能使用此數據(點擊)