2012-03-07 64 views
1

比方說,我已經創建了UIView的子類,並且用nib文件加載它。
我這樣做:繼承和覆蓋用nib文件創建的UIView

MySubView.m 

- (id)initWithFrame:(CGRect)frame 
{ 
    self = [super initWithFrame:frame]; 
    if (self) { 
     NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"MySubView" owner:self options:nil]; 

     [self release]; 
     self = [[nib objectAtIndex:0] retain]; 
     self.tag = 1; 
     [self fire]; 
    } 
    return self; 
} 

- (void)fire { 
    NSLog(@"Fired MySubView"); 
} 

現在我想創造一些變化,但我不希望複製筆尖文件,所以我儘量繼承MySubView這樣,改變背景顏色:

RedMySubView.m 


- (id)initWithFrame:(CGRect)frame 
    { 
     self = [super initWithFrame:frame]; 
    if (self) { 
     self.backgroundColor = [UIColor redColor]; 
     [self fire]; 
    } 
    return self; 
} 

- (void)fire { 
    NSLog(@"Fired RedMySubView"); 
} 

視圖被創建,背景顏色被改變,但火焰動作不被子類覆蓋。如果我調用fire方法,則控制檯中的結果爲Fired MySubView
我該如何解決這個問題?
我想保持筆尖佈局,但給它一個新的類。

+0

檢查此question iNeal 2012-03-16 10:11:19

回答

0

我會說在MySubview初始化程序initWithFrame中使用[self release]時,您正在拋出您想使用初始化程序創建的類。該類由loadNibName方法加載,因此具有與nib中定義的類相同的類。 因此,在子類中調用初始化器是沒有用的。

試圖實現在MySubview自己筆尖的構造函數(如initWithNibFile):

- (id) initWithNibFile:(NSString *) nibName withFrame:(CGRect) frame 

等,並調用此構造中RedMySubview

- (id) initWithNibFile:(NSString *) nibName withFrame:(CGRect) frame { 
self = [super initWithNibFile:mynib withFrame:MyCGRect]; 
if (self) 
.... 

如果你現在去查找你的筆尖文件真的有RedMySubview作爲類,應該是 覆蓋。如果您使用均爲 MySubview和RedMySubview,則必須複製xib。 或者你創建一個抽象類(存根),它實現的只是要創建initWithNibFile初始化和UIViews是它的子類:

MyAbstractNibUIView initWithNibFile:withFrame: 
MyRedSubview : MyAbstractNibUIView  red.xib 
MyGreenSubview :MyAbstractNibUIView  green.xib 
MyBlueSubview : MyAbstractNibUIView  blue.xib 
0

當你調用self = [[nib objectAtIndex:0] retain]你基本上覆蓋你的「自我」的對象,成爲一個MySubView,因爲MySubView是nib文件中的基礎對象。這是不受歡迎的,因爲如果調用類是一個RedMySubView,那麼它將被覆蓋到一個MySubView中。

相反,你想改變你的- (id)initWithFrame:(CGRect)frame在MySubView成這樣:

- (id)initWithFrame:(CGRect)frame 
{ 
    self = [super initWithFrame:frame]; 
    if (self) { 
     NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"MySubview" owner:self options:nil]; 

     // The base of the nib file. Don't set self to this, instead copy all of its 
     // subviews, and "self" will always be the class you intend it to be. 
     UIView *baseView = [nib objectAtIndex:0]; 

     // Add all the subviews of the base file to your "MySubview". This 
     // will make it so that any subclass of MySubview will keep its properties. 
     for (UIView *v in [baseView subviews]) 
      [self addSubview:v]; 

     self.tag = 1; 
     [self fire]; 
    } 
    return self; 
} 

現在,一切都應該在「MyRedSubView」的初始化工作,除了消防將火兩次,因爲你在MySubView叫它都和RedMySubView。