50
votes

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.

3
if you use synthesize (i guess you do) and you use a modern compiler (i guess you do because of ios5) you don't need to declare the ivar, objective-c does that automatically for you. (this is not the answer to your question, just a sidenote).choise
This is a good thing to know, I always declared ivars for properties up to now. And yes, I do @synthesize the property with the default name.Alex Stone
Was about to tell you the same thing as @choise. And I believe you still get the benefit of ARC regardless of whether or not you use the property.Undeadlegion
You don't even need @synthesizenielsbot

3 Answers

68
votes

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

5
votes

No you shouldn't!

You can find description why here
Also apple recommend to don't do it. Read here

0
votes

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

Since the dot notation is still an Objective-C method (and a C method actually under the ObjC method) the dot notation, or calling the method, is perfectly safe GIVEN the method is prepared to deal with underlying type(s) in memory in whatever state they happen to be in. The normal rule about avoiding use of an uninitiatilized (possibly) garage memory segment still would apply. Which is the strongest motivation for use of the ivar in the init.

But if your method (getter|setter) is capable of correctly using the memory segment - independent of whether it is first written to before being read - then by all means use your getter in the init method. A Lazy getter takes advantage of the assumption that a pointer it will initialize starts as 'nil' to decide on performing the initialization. If you cannot assume the initial contents of your memory then initializing the ivar might be the safest course.

Why have the rule of never using setters or getters in the init if the method is capable of operating correctly in this scenario?