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

Ale*_*one 50 initialization reference-counting objective-c ios5 automatic-ref-counting

一个简单的问题.

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

在.h文件中:

(Reminder*)reminder;
@property(nonatomic,strong)(Reminder*)reminder;
Run Code Online (Sandbox Code Playgroud)

在.m文件中,如果我使用ARC,我应该在init方法中使用ivar还是属性?

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

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

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

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

jus*_*tin 67

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

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

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

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

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

注意:我使用"部分构造",因为初始化只是图片的一半; -dealloc有类似的警告.

有关为什么应该在部分构造状态(ARC || MRC)中使用直接访问的更多细节可以在这里找到:初始化属性,点表示法

  • @Zhang我认为从子类'init中的超类调用属性是安全的.到达子类'init的"body"时,超类'init应该已经完成​​了.这意味着,超类本身(或至少应该,如果写得正确)已经完全初始化.因此,访问其(=超类')属性应该是安全的 - 即使您重写子类中的属性.问题是当您在超类中访问init中的属性时.在这种情况下,如果覆盖子类中的setter,则可以使用部分初始化的对象到达那里. (2认同)

Kos*_*val 5

不,你不应该!

你可以在这里找到描述为什么
苹果也建议你不要这样做.在这里阅读