衆所周知,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測試