2012-03-07 65 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。