我创建了一个UIView
的子类,它有一个固定的框架。那么,我可以覆盖init
而不是initWithFrame:
吗? E.g:
- (id)init {
if ((self = [super initWithFrame:[[UIScreen mainScreen] bounds]])) {
self.backgroundColor = [UIColor clearColor];
}
return self;
}
-initWithFrame:
的Xcode文档说:“如果以编程方式创建视图对象,则此方法是UIView
类的指定初始化程序。子类可以覆盖此方法以执行任何自定义初始化但必须在实施开始时致电super
。“
“指定初始化程序”是什么意思?
答案 0 :(得分:73)
指定的初始值设定项是所有其他初始化程序必须调用的初始值设定项。 UIView
和子类有点不寻常,因为他们实际上有两个这样的初始化器:-initWithFrame:
和-initWithCoder:
,具体取决于视图的创建方式。如果要在代码中实例化视图,则应覆盖-initWithFrame:
;如果从笔尖加载视图,则应覆盖-initWithCoder:
。或者,您可以将代码放在第三种方法中,并覆盖这些初始化程序,以便它们调用第三种方法。事实上,这通常是推荐的策略。
因此,例如,您可以创建一个UIView子类ClueCharacter
,它具有自己的初始化方法:-initWithPerson:place:thing:
。然后,您可以像这样创建视图:
的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:
就可以了。
答案 1 :(得分:23)
UIView
的{{1}}中的完全等于[super init]
答案 2 :(得分:3)
在具有多个初始化程序的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:
以及使用正常尺寸调用init:
的香草initWithFrame:
。通常的惯例是,您可以在子类中的init
上添加新的变体,但不应该删除,并且您始终在指定的初始化程序中执行实际的初始化工作。这允许来自父类的任何初始化方法,你没有提供仍然适合你的子类的新实现。