Search code examples
objective-cios5initializationautomatic-ref-countingreference-counting

Should I refer to self.property in the init method with ARC?


A quick question.

if I have a property and an ivar declared with the same name:

in the .h file:

(Reminder*)reminder;
@property(nonatomic,strong)(Reminder*)reminder;

in the .m file, should I use the ivar or the property in the init method if I'm using ARC?

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

Or should I use the property to get the benefit of the automatic reference counting like this:

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

I'm not sure at which point in the object's initialization the properties become accessible with the dot notation.


Solution

  • Use direct access in partially constructed states, regardless of ARC:

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

    This is because self.whatever will trigger other side effects, such as Key-Value Observing (KVO) notifications, or maybe your class implements (explicitly) or a subclass overrides setWhatever: -- and that could expose your partially initialized instance to other APIs (including its own), which rightly assume they are dealing with a fully constructed object.

    You could manually verify that a class is capable of operating in a partially initialized state, but that requires a lot maintenance and is (frankly) impractical or impossible when other people want to subclass your class. It requires a lot of time and maintenance, and there isn't substantiative benefit doing so, especially if you try to use the approach as a convention.

    So the uniform manner which guarantees correctness is to use direct access in partially constructed states, and avoid using the accessors.

    Note: I am using "partially constructed" because initialization is only half of the picture; -dealloc has similar caveats.

    Some more detail as to why you should use direct access in partially constructed states (ARC || MRC) can be found here: Initializing a property, dot notation