Surfer
Surfer

Reputation: 109

What is @synthesize foo = _foo all about?

Why does one want this underscore prefix in an iOS app?

Upvotes: 10

Views: 982

Answers (4)

jerrylroberts
jerrylroberts

Reputation: 3454

Sometimes it helps to see whats happening behind the scenes to understand. Basically when you see this

@property (nonatomic, retain) Foo *foo;

With this in the implementation

@synthesize foo=_foo;

It's syntax sugar for the following, meaning that the compiler basically generates this code for you

Foo *foo = nil;

-(Foo *) foo {
    return _foo;
}

-(void) setFoo:(Foo *)val {
    if( _foo != val ) {
        [_foo release];
        _foo = [val retain];
    }
}

This way when you refer to the public property, you hit it through the generated accessories of self.foo and if you want to refer to the instance variable inside your class you can refer to _foo. Before XCode four it was easy to get confused between the two. You could do something like

self.foo = foo1;

foo = foo2;

This was perfectly legal and could cause problems on a couple levels. The second line doesn't use the accessor so foo2 would not be retained which could cause it to be picked up by garbage collection prematurely. Even worse, the second line doesn't use the accessor which would release any previous value meaning it would cause a memory leak.

So in summary, the new technique creates a getter and setter for you property and allows you to also specify the name to be used for the instance variable, used for encapsulation.

Upvotes: 3

Salam Horani
Salam Horani

Reputation: 101

just wanted to add my thoughts to all the above answers.

in my case, i use it mainly to keep my classes safe from accidents.

in my .h files, i declare only the properties with no ivars. in the .m file, i use the above @synthesize pattern to hide the actual ivar from users, including myself, to be forced to use the synthesized/dynamic accessors and not the otherwise ivars directly. you could use anything for your ivar name and not just underscore it. e.g. you could do:

@synthesize foo = _mySecretFoo;
@synthesize bar = oneUglyVarBecauseIHateMyBoss;

this way, your boss would only see bar, and you would find it much easier, and thus safer, to use the bar accessor - whether you use dot notation or messages.

i prefer this approach over the other,

@property (getter=foo, setter=setFoo, ...) _mySecretFoo;
@property (getter=bar, setter=setBar, ...) oneUglyVarBecauseIHateMyBoss;

as this does not enforce private implementation and encapsulation, and it's just extra typing when Xcode can do the same for you. one thing to remember, properties are not the same as ivars! you could have more properties than ivars, or the other way around.

Upvotes: 1

Ryan Crews
Ryan Crews

Reputation: 3033

Here's why I do this at times:

If I want to do lazy loading on a property I will typically underscore my ivar so that the work done to load the desired data from the back-end server/saved file/what-have-you is only loaded the first time. For example:

- (NSMutableArray *)recentHistory;
{
   if (_recentHistory == nil)
   {
       // Get it and set it, otherwise no work is needed... hooray!
   }

   return _recentHistory;
}

So here calls to the property [instanceOfClass recentHistory] (or instanceOfClass.recentHistory) will check the ivar to see if it needs to load the data or just return the already loaded data.

It is overkill to declare all of your properties this way.

Hope that helps.

Upvotes: 1

Vitor Furlanetti
Vitor Furlanetti

Reputation: 451

it's a convention to keep the ivar (instance variables) safe, so you can only access it through the getter and setter.

Upvotes: 0

Related Questions