初始化对象的最佳方法是什么?

时间:2013-08-12 16:04:41

标签: ios objective-c

我已经使用Objective-C几年了,但我仍然不确定如何初始化一个对象。我们的问题是:

-(id)init {
    self = [super init];
    if (self) {
        self.backgroundColor = [UIColor blueColor];
        self.textColor = [UIColor greenColor];
    }
    return self;
}

-(id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        self.backgroundColor = [UIColor yellowColor];
    }
    return self;
}

在两种方法中对其进行初始化同样意味着复制和粘贴编码(巨大的禁忌,由于人为错误导致无穷无尽的问题,例如值不同,如上例所示)或新方法:

-(id)init {
    self = [super init];
    if (self) {
        [self initialSetup];
    }
    return self;
}

-(id)initialSetup {
    self.backgroundColor = [UIColor blueColor];
    self.textColor = [UIColor greenColor];
}

这就产生了一个问题,即如果子类有initialSetup方法,则调用[self initialSetup]的超类将调用子类的initialSetup,从而忽略所有超类的设置。您可以通过每次附加类名来解决此问题,例如initialSetupTextField

但这似乎相当混乱。这只是初始化一个对象。其他人如何做到这一点?

3 个答案:

答案 0 :(得分:9)

每个类都应该有一个指定的初始化程序;必须始终调用一个真正的init...方法变体来正确初始化类(如Matt所述)。

然而,这并没有完全解决这个问题,因为一个类也可能通过unarchival支持实例化,这会在你的问题中遇到同样的“我在哪里放置常见的初始化goop”问题。

通常,我创建一个方法,如:

- (void)commonInit
{
     ... common initialization goop goes here ...
}

然后从指定的初始化程序和/或initWithCoder:将其称为

是的,有点乱,但你可以做的不多。

减少混乱的一般策略:

•提供非常少的初始化器;也许init +一个初始化程序,包含其他配置的所有可能参数。

•将super的初始化程序指定为您的DI,并通过它调用任何其他初始化程序。当你有一个更具体的DI的子类化时(见UIView的{​​{1}}),覆盖超级的DI来调用initWithFrame:然后调用[self initFancy:...]

答案 1 :(得分:8)

你错过了Designated Initializer的概念。你编写了一个执行繁重工作的init方法。所有其他初始化程序只调用指定的初始化程序。您的示例如下所示:

-(id)init {
    return [self initWithFrame:CGRectZero];
}

-(id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        self.backgroundColor = [UIColor yellowColor];
    }
    return self;
}

答案 2 :(得分:1)

  

...每次都附加班级名称,例如-initialSetupTextField

是的,正是如此,或者您可以为私有实例初始化例程创建一个C函数 - 当指定的初始化程序不足时。我使用了与你不同的命名方案,但只要你使用避免碰撞的约定,那么你就是好的。我之所以提到这一点,是因为你的例子中的方法可能会混淆吸气剂。

我做的另一件事是从此例程返回一个值,指示是否存在错误(即应返回nil)。