开发者

What is @synthesize foo = _foo all about?

开发者 https://www.devze.com 2023-04-01 04:06 出处:网络
Why does one want this underscore prefix in an 开发者_如何学CiOS app?Sometimes it helps to see whats happening behind the scenes to understand.Basically when you see this

Why does one want this underscore prefix in an 开发者_如何学CiOS app?


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.


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.


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.


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

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号