假设我已经创建了UIView的子类,并且我用nib文件加载它。
我这样做:
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");
}
现在我想创建一些变体,但我不想复制nib文件,所以我尝试像这样子类化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操作。如果我调用fire
方法,则控制台中的结果为Fired MySubView
我该如何解决这个问题?
我想保留笔尖布局,但是给它一个新的类。
答案 0 :(得分:1)
我会说,在MySubview初始化程序initWithFrame中使用[self release],您将丢弃要使用初始化程序创建的类。该类由loadNibName方法加载,因此具有与nib中定义的相同的类。 因此,在子类中调用初始化程序是没用的。
尝试在MySubview中实现自己的nib构造函数(例如initWithNibFile):
- (id) initWithNibFile:(NSString *) nibName withFrame:(CGRect) frame
等。并在RedMySubview中调用此构造函数
- (id) initWithNibFile:(NSString *) nibName withFrame:(CGRect) frame {
self = [super initWithNibFile:mynib withFrame:MyCGRect];
if (self)
....
如果您现在查找您的nib文件确实将RedMySubview作为类,那应该是fire 重写。如果您使用两者 MySubview和RedMySubview,则必须复制xib。 或者您创建一个抽象类(存根),它只实现initWithNibFile初始化程序,您想要创建的UIViews是它的子类:
MyAbstractNibUIView initWithNibFile:withFrame:
MyRedSubview : MyAbstractNibUIView red.xib
MyGreenSubview :MyAbstractNibUIView green.xib
MyBlueSubview : MyAbstractNibUIView blue.xib
答案 1 :(得分:1)
当你调用self = [[nib objectAtIndex:0] retain]
时,你基本上覆盖你的“self”对象成为MySubView,因为MySubView是nib文件中的基础对象。这是不受欢迎的,因为如果调用类是RedMySubView,那么它将被重写为MySubView。
相反,您希望将MySubView中的- (id)initWithFrame:(CGRect)frame
更改为:
- (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”的初始化程序中起作用,除了fire会激发两次,因为你在MySubView和RedMySubView中都调用它。