iOS:UIView子类init或initWithFrame:?
我做了一个具有固定框架的UIView
的子类。 所以,我可以重写init
而不是initWithFrame:
例如:
- (id)init {
if ((self = [super initWithFrame:[[UIScreen mainScreen] bounds]])) {
self.backgroundColor = [UIColor clearColor];
}
return self;
}
-initWithFrame:
的Xcode文档说:“如果以编程方式创建视图对象,则此方法是UIView
类的指定初始值设定项。子类可以重写此方法以执行任何自定义初始化,但必须在实现开始时调用super
。 “
“指定初始值设定项”是什么意思?
指定的初始化器是所有其他初始化器必须调用的初始化器。 UIView
和子类有点不寻常,因为它们实际上有两个这样的初始化程序: -initWithFrame:
和-initWithCoder:
取决于如何创建视图。 你应该重写-initWithFrame:
如果你正在代码中实例化视图, -initWithCoder:
如果你从一个笔尖加载它。 或者,您可以将代码放在第三个方法中,并覆盖这两个初始化方法,以便他们调用第三个方法。 事实上,这通常是推荐的策略。
因此,例如,您可以创建一个UIView子类ClueCharacter
,该子类具有自己的初始化方法: -initWithPerson:place:thing:
ClueCharacter
然后,您可以像这样创建您的视图:
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
}
}
如果你想调用你的子类的initializer -init
,只要你在实现中调用了-initWithFrame:
。
在UIView
调用[super init]
完全等于[super initWithFrame:CGRectZero]
在具有多个初始程序的Objective-C类中,指定的初始化程序是执行有意义工作的程序。 所以,通常你有一个有几个初始者的班级,他说:
- (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];
}
如果一个班级只有一个初始者,那么这就是指定的初始者。
在你的情况下,按照最佳做法,你应该实现initWithFrame:
并且也是一个vanilla init:
调用initWithFrame:
用你的正常尺寸。 正常的约定是你可以在子类中的init
中添加新的变体,但不应该带走任何东西,并且你总是在指定的初始化程序中进行实际的初始化工作。 这允许父类中的任何初始化方法都不会提供新的实现,仍然可以与您的子类适当地协作。