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
中添加新的变体,但不应该带走任何东西,而且你总是在指定的初始化程序中进行实际的初始化工作。 这允许父类中的任何初始化方法都不会提供新的实现,仍然可以与您的子类适当地一起工作。