iOS:UIView的子类init或initWithFrame:?

我做了一个具有固定框架的UIView的子类。 所以,我可以重写init而不是initWithFrame: 例如:

 - (id)init { if ((self = [super initWithFrame:[[UIScreen mainScreen] bounds]])) { self.backgroundColor = [UIColor clearColor]; } return self; } 

-initWithFrame:的Xcode文档说:“如果以编程方式创build视图对象,则此方法是UIView类的指定初始值设定项。子类可以重写此方法以执行任何自定义初始化,但必须在实现开始时调用super 。 “

“指定初始值设定项”是什么意思?

指定的初始化器是所有其他初始化器必须调用的初始化器。 UIView和子类有点不寻常,因为它们实际上有两个这样的初始化程序: -initWithFrame:-initWithCoder:这取决于如何创build视图。 你应该重写-initWithFrame:如果你正在代码中实例化视图, -initWithCoder:如果你从一个笔尖加载它。 或者,你可以把你的代码放在第三个方法中,并重写这两个初始化方法,这样他们就可以调用第三个方法。 事实上,这通常是推荐的策略。

所以,例如,你可以创build一个UIView子类, ClueCharacter ,它有自己的初始化方法: -initWithPerson:place:thing: ClueCharacter 然后,您可以像这样创build您的视图:

OBJ-C:

 ClueCharacter *mustard = [[ClueCharacter alloc] initWithPerson:@"Col. Mustard" place:kInTheStudy thing:kTheRope]; 

迅速:

 var mustard = ClueCharacter("Col. Mustard", place: kInTheStudy, thing: kTheRope) 

这很好,但为了初始化对象的UIView部分,您的方法必须调用指定的初始值设定项:

OBJ-C:

 -(id)initWithPerson:(NSString*)name place:(CluePlace)place thing:(ClueWeapon)thing { if ((self = [super initWithFrame:CGRectMake(0, 0, 150, 200)])) { // your init stuff here } } 

迅速:

 func init(name: String, place : CluePlace, thing : ClueWeapon) { if (self = super.init(CGRectMake(0, 0, 150, 200))) { // your init stuff here } } 

如果你想调用你的子类的初始化-init ,那么只要你在实现中调用了-initWithFrame:

UIView调用[super init]是完全等于[super initWithFrame:CGRectZero]

在具有多个初始者的Objective-C类中,指定的初始者是进行有意义的工作的人。 所以,经常你有一个有几个初始者的class级,他说:

 - (id)initWithRect:(CGRect)someRect; - (id)initWithRect:(CGRect)someRect setDefaultColour:(BOOL)setDefaultColour; - (id)initWithRect:(CGRect)someRect setDefaultColour:(BOOL)setDefaultColour linkTo:(id)someOtherObject; 

在这种情况下,你通常会(但不是总是)说第三个是指定的初始化程序,并执行另外两个例如

 - (id)initWithRect:(CGRect)someRect { return [self initWithRect:someRect setDefaultColour:NO]; } - (id)initWithRect:(CGRect)someRect setDefaultColour:(BOOL)setDefaultColour { return [self initWithRect:someRect setDefaultColour:setDefaultColour linkTo:nil]; } 

如果一个class级只有一个初始者,那么这就是指定的初始者。

在你的情况下,按照最佳做法,你应该实现initWithFrame:也是一个香草init:调用initWithFrame:与你的正常尺寸。 正常的约定是,你可以在子类中的init中添加新的变体,但不应该带走任何东西,而且你总是在指定的初始化程序中进行实际的初始化工作。 这允许父类中的任何初始化方法都不会提供新的实现,仍然可以与您的子类适当地一起工作。