iOS:UIView 子类 init 或 initWithFrame:?

发布于 2024-11-30 06:41:02 字数 464 浏览 1 评论 0原文

我创建了一个具有固定框架的 UIView 子类。那么,我可以重写 init 而不是 initWithFrame: 吗?例如:

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

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

“指定初始化器”是什么意思?

I made a subclass of UIView that has a fixed frame. So, can I just override init instead of initWithFrame:? E.g.:

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

The Xcode documentation for -initWithFrame: says: "If you create a view object programmatically, this method is the designated initializer for the UIView class. Subclasses can override this method to perform any custom initialization but must call super at the beginning of their implementation."

What does "designated initializer" mean?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

我不会写诗 2024-12-07 06:41:02

指定的初始化器是所有其他初始化器都必须调用的初始化器。 UIView 和子类有点不寻常,因为它们实际上有两个这样的初始化器:-initWithFrame:-initWithCoder:,具体取决于如何实现视图已创建。如果您在代码中实例化视图,则应覆盖 -initWithFrame:;如果您从笔尖加载视图,则应覆盖 -initWithCoder:。或者,您可以将代码放在第三个方法中并重写这两个初始值设定项,以便它们调用您的第三个方法。事实上,这通常是推荐的策略。

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

Obj-C:

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

Swift:

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
    }
}

Swift:

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

如果你想调用子类的初始化器-init,只要在实现中调用-initWithFrame:就可以了。

The designated initializer is the one that all the other initializers must call. UIView and subclasses are a little unusual in that they've actually got two such initializers: -initWithFrame: and -initWithCoder:, depending on how the view is created. You should override -initWithFrame: if you're instantiating the view in code, and -initWithCoder: if you're loading it from a nib. Or, you could put your code in third method and override both those initializers such that they call your third method. In fact, that's often the recommended strategy.

So, for example, you might create a UIView subclass, ClueCharacter, that has its own initialization method: -initWithPerson:place:thing:. You then create your view like this:

Obj-C:

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

Swift:

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

That's fine, but in order to initialize the UIView part of the object, your method must call the designated initializer:

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
    }
}

Swift:

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

If you want to call your subclass's initializer -init, that's okay as long as you call -initWithFrame: in the implementation.

水染的天色ゝ 2024-12-07 06:41:02

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

in UIView calling [super init] is exactly equal to [super initWithFrame:CGRectZero]

转瞬即逝 2024-12-07 06:41:02

在具有多个初始化程序的 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: 以及使用正常尺寸调用 initWithFrame: 的普通 init: 。通常的约定是,您可以在子类中的 init 上添加新的变体,但不应删除任何变体,并且您始终在指定的初始化程序中执行实际的初始化工作。这允许您未提供新实现的父类中的任何初始化方法仍然可以与您的子类正常工作。

In an Objective-C class with multiple initialisers, the designated initialiser is the one that does the meaningful work. So, often you have a class with a few initialisers, say:

- (id)initWithRect:(CGRect)someRect;

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

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

In that case you'd normally (but not always) say that the third was the designated initialiser, and implement the other two as e.g.

- (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];
}

If a class has only one initialiser then that's the designated initialiser.

In your case to follow best practice you should implement initWithFrame: and also a vanilla init: that calls initWithFrame: with your normal dimensions. The normal convention is that you can add new variations on init in subclasses, but shouldn't take any away, and that you always do the actual initialising work in the designated initialiser. That allows any initialising methods from the parent class that you don't provide new implementations of still to work appropriately with your subclass.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文