天天看點

initWithNibName和viewDidLoad執行順序

衆所周知,IB在加載nib的過程中存在着一些undocument行為,有的行為确實是不可理喻的,是以程式員對IB産生了抗拒心理。

今天我們要介紹的是IB導緻的一個奇特行為。通過本文的描述, 作者完美地展示了IB給面向對象所帶來的破壞作用。

我們有兩個View Controller,暫名為superclass和subclass。subclass繼承了superclass。

在superclass的initWithNibName初始化方法中:

self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        [self setWords:@”somebody is knocking”];
}
return self;
           

在superclass的viewDidLoad方法中:

[super viewDidLoad];
NSLog(@"get XXX:%@", [self words]);
           

然後我們用subclass繼承superclass。在initWithNibName方法中:

self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {[
        [self setWords:@” pleaseanswer the door”];
}
           

很顯然,我們通過覆寫initWithNibName方法,修改了從superclass繼承來的words屬性。如果我們想列印pleaseanswer the door這段文本,你可能會想重用superclass的viewDidLoad方法:

- (void)viewDidLoad{
    [super viewDidLoad];  
}
           

好了,運作程式。在加載superclass.xib時,控制台将列印somebodyis knocking。而加載subclass.xib時,控制台會列印pleaseanswer the door。

Hey,等一等。為什麼我會在兩個ViewController中都看到了somebody is knocking?

不用看了,subclass對象的words屬性确實是please answer the door。如果你正在調試代碼,那麼可以debug區中确認這一點。

問題在于subclass的初始化出現了問題。看這一句:self=[super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];

這句代碼将導緻IB加載nib檔案,并立即調用viewDidLoad方法。我們可以看到在初始化subclass時的調用順序如下:

1. subclass->initWithNibName

2. superclass->initWithNibName

3. superclass->setWords

4. subclass->viewDidLoad

5. superclass->initWithNibName

6. subclass->setProperty

讓我再解釋一下:

1. 首先subclass的initWithNIbName方法調用。

2. 接着調用superclass的initWithNibName方法。

3. 在superclass的initWithNibName方法中,words屬性被設定為somebodyis knoking。

4. superclass的initWithNibName方法結束,表示nib檔案已加載,則調用nib檔案的File’sowner所指向的 viewDidLoad方法。注意,這時的nib檔案名應為subclass.nib,于是應調用[subclass viewDidLoad]方法。

5. subclass的viewDidLoad方法又調用了supclass的viewDidLoad方法。于是控制台列印出的是words屬性的目前值somebodyis knoking。

6. 最後才是initWithNibName方法剩餘的代碼,在這裡我們将words屬性修改為pleaseanswer the door。但為時已晚,在此之前viewDidLoad已經執行結束。

解決的辦法是簡單的,不要在initWithName方法中修改從父類繼承來的屬性,相反,我們可以在[super iewDidLoad]之前這樣做:

- (void)viewDidLoad{

[selfsetWords:@” pleaseanswer the door”];

    [super viewDidLoad];  

}

結論

由于initWithNibName或者是IB 這些限制,.nib檔案違反了面向對象的原則。.nib檔案無法從另一個.nib檔案繼承。不管你的類如何繼承,但nib檔案中不會儲存類的層次結構,File’sowner也無法指向類鍊。

thx:http://blog.csdn.net/kmyhy/article/details/7236619

btw:

現在是

1. subclass->initWithNibName

2. superclass->initWithNibName

3. superclass->setWords

4. subclass->setWords

5. subclass->viewDidLoad

6. superclass->viewDidLoad

列印:在加載superclass.xib時,控制台将列印somebodyis knocking。而加載subclass.xib時,控制台會列印pleaseanswer the door。

以上ios6測試