inheritance从nib加载的UIView子类

我有一个类, FooView ,这是UIView的子类,其视图是从一个笔尖加载,如下所示:

 + (instancetype)viewFromNib { NSArray *xib = [[NSBundle mainBundle] loadNibNamed:@"FooView" owner:self options:nil]; return [xib objectAtIndex:0]; } 

笔尖本身的自定义类在Identity Inspector中设置为FooView

这被实例化为:

 FooView *view = [FooView viewFromNib]; 

这就像你所期望的那样。 但是,当FooView本身被子类化为FooSubclassView,并且实例化为:

 FooSubclassView *view = [FooSubclassView viewFromNib]; 

view仍然是FooSubclassViewtypes,而不是FooSubclassView

使用object_setClass调整类并不能解决底层对象是FooView实例的问题,因此在子类实例上调用的方法将是超类( FooSubclassView )的方法,而不是FooSubclassView

我怎样才能纠正这个问题,使子类是正确的types,而不必为每个子类创build一个新的笔尖,或者不得不在每个子类中重新实现viewFromNib

Swizzling不是(永远)答案。

问题在于你的NIB; 它被归档为对象[0]是FooSubclassView一个实例,而不是FooSubclassView 。 如果要使用与对象[0] 不同的视图子类加载相同的 NIB,则需要将实例移出NIB的存档。

可能是最容易做的事情,因为你的类已经加载了NIB,所以使FooSubclassViewFooSubclassView的实例成为文件的所有者

这个问题有一个文件的所有者模式的体面的解释。 请注意,你已经在那里了,因为你的类正在加载XIB / NIB。

这里是文件所有者的官方文档 。

我不确定你是否find了最好的解决scheme,但我认为这是你正在寻找的。

 + (instancetype)viewFromNib { NSString *className = NSStringFromClass([self class]); NSArray *xib = [[NSBundle mainBundle] loadNibNamed:className owner:self options:nil]; return [xib objectAtIndex:0]; } 

只要你能确定NIB与class级同名,


在意识到我错误的要求之一后,我说我必须同意@ bbum。

 - (id)init { // NOTE: If you don't know the size, you can work this out after you load the nib. self = [super initWithFrame:GCRectMake(0, 0, 320, 480)]; if (self) { // Load the nib using the instance as the owner. [[NSBundle mainBundle] loadNibNamed:@"FooView" owner:self options:nil]; } return self; } + (instancetype)viewFromNib { return [[self alloc] init]; }