我应该在ARC的init方法中引用self.property吗?

时间:2011-11-08 19:46:09

标签: objective-c ios5 initialization automatic-ref-counting reference-counting

一个简单的问题。

如果我有一个属性和一个用相同名称声明的ivar:

<。>文件中的

(Reminder*)reminder;
@property(nonatomic,strong)(Reminder*)reminder;
<。>在.m文件中,如果我使用ARC,我应该在init方法中使用ivar还是属性?

- (id)initWithReminder:(Reminder*)reminder_ {
    self = [super init];
    if (self) {
        reminder = reminder_;
    }
    return self;
}

或者我应该使用该属性来获得自动引用计数的好处,如下所示:

- (id)initWithReminder:(Reminder*)reminder_ {
    self = [super init];
    if (self) {
        self.reminder = reminder_;
    }
    return self;
}

我不确定在对象的初始化中哪个点可以通过点表示法访问属性。

3 个答案:

答案 0 :(得分:67)

在部分构造的状态下使用直接访问,无论ARC如何:

- (id)initWithReminder:(Reminder*)reminder_ {
    self = [super init];
    if (self) {
        reminder = reminder_;
        // OR
        reminder = [reminder_ retain];
    }
    return self;
}

这是因为self.whatever会触发其他副作用,例如键值观察(KVO)通知,或者您的类实现(显式)或子类覆盖setWhatever: - 这可能将部分初始化的实例暴露给其他API(包括它自己的),这正确地假设它们正在处理完全构造的对象。

可以手动验证某个类是否能够在部分初始化状态下运行,但这需要大量维护,并且(当然)当其他人想要为您的类创建子类时,这是不切实际或不可能的。它需要大量的时间和维护,并且没有这样做的实质性好处,特别是如果您尝试将该方法用作约定。

因此,保证正确性的统一方式是在部分构造的状态下使用直接访问,并避免使用访问器。

注意:我正在使用“部分构造”,因为初始化只是图片的一半; -dealloc也有类似的警告。

有关在部分构建状态(ARC || MRC)中使用直接访问的原因的更多详细信息,请访问:Initializing a property, dot notation

答案 1 :(得分:5)

不,你不应该!

您可以找到here为何的说明 苹果也建议不要这样做。 Read here

答案 2 :(得分:0)

  

我不确定在对象的初始化中哪个点可以通过点表示法访问属性。

由于点符号仍然是Objective-C方法(以及实际上在ObjC方法下的C方法),点符号或调用方法是完全安全的GIVEN该方法准备处理基础类型在他们恰好处于的任何状态的记忆中。 关于避免使用未经过处理的(可能的)车库存储器段的正常规则仍然适用。这是在初始化中使用ivar的最强烈动机。

但是如果你的方法(getter | setter)能够正确使用内存段 - 无论是在读取之前是否首次写入 - 那么一定要在init方法中使用你的getter。 懒惰的getter利用了它初始化的指针开始为'nil'来决定执行初始化的假设。如果你不能假设你的记忆的初始内容,那么初始化ivar可能是最安全的课程。

如果方法在这种情况下能够正确运行,为什么在init中永远不会使用setter或getter的规则?