Reputation: 237
I am trying to understand the purpose of the synthesize
directive with property name overriding. Say that I have an interface defined as follow:
@interface Dummy ... {
UILabel *_dummyLabel;
}
@property (retain, nonatomic) UILabel *dummyLabel;
And in the implementation file, I have:
@synthesize dummyLabel = _dummyLabel;
From what i understand, "dummyLabel" is just an alias of the instance variable "_dummyLabel". Is there any difference between self._dummyLabel and self.dummyLabel?
Upvotes: 15
Views: 15651
Reputation: 4647
Old post, but I think its important to mention, that it is recommended to access variables via getters and setters (so, with dot notation). Accessing a field directly (_ivar) is strongly recommended only when initializing it.
There is some good Apple's article: https://developer.apple.com/library/ios/#documentation/cocoa/conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html
Last paragraph:
You should always access the instance variables directly from within an initialization method because at the time a property is set, the rest of the object may not yet be completely initialized. Even if you don’t provide custom accessor methods or know of any side effects from within your own class, a future subclass may very well override the behavior.
Upvotes: 0
Reputation: 163228
Yes. self._dummyLabel
is undefined, however _dummyLabel
is not.
Dot syntax expands out to simple method invocations, so it's not specific to properties. If you have a method called -(id)someObject
, for example in the case of object.someObject
, it will be as if you wrote [object someObject];
.
self.dummyLabel //works
self._dummyLabel //does not work
dummyLabel //does not work
_dummyLabel //works
[self dummyLabel]; //works
[self _dummyLabel]; //does not work
Upvotes: 24
Reputation: 2352
The advantage of having another name for the ivar than for the property is that you can easily see in the code when you are accessing one or the other - Andre K
I'm not able to find a 'comment' button so I'm having to post as an 'answer'.
Just wanted to expand on Andre's comment - by knowing when you are using the synthesized properties vs the vanilla variable, you know (especially in case of setters) when a variable is being retained/copied/released automatically thanks to your nice setter, vs being manipulated by hand.
Of course if you are doing things right, you probably don't need the help of a setter to retain/release objects properly! But there can be other scenarios too where referring to your ivars as self.ivar
instead of _ivar
can be helpful, such as when you are using custom setters/getters instead of the default synthesized ones. Perhaps every time you modify a property, you also want to store it to NSUserDefaults. So you might have some code like this:
@interface SOUserSettings : NSObject {
BOOL _autoLoginOn;
}
@property (nonatomic, assign) BOOL autoLoginOn;
@end
@implementation SOUserSettings
@synthesize autoLoginOn = _autoLoginOn;
- (void)setAutoLoginOn:(BOOL)newAutoLoginOnValue {
_autoLoginOn = newAutoLoginOnValue;
[[NSUserDefaults standardUserDefaults] setBool:_autoLoginOn forKey:@"UserPrefAutoLoginOn"];
}
@end
Note: This is just illustrative code, there could be a thousand things wrong with it!
So now, in your code, if you have a line that says _autoLoginOn = YES
- you know it's not going to be saved to NSUserDefaults, whereas if you use self.autoLoginOn = YES
you know exactly what's going to happen.
The difference between _autoLoginOn
and self.autoLoginOn
is more than just semantic.
Upvotes: 13
Reputation: 4227
I don't see any big advantage of renaming _dummyLabel to dummyLabel
In some ObjC runtimes you have a hard time making instance variables invisible to users of the class. For them sticking some prefix (or suffix) on your instance variables can make it clear (or more clear) that you don't want anyone messing with your variables. However you don't want that gunk on your public functions. This lets you get it off.
It could also be useful if you need to maintain an old interface with one set of names at the same time as a new set of APIs with a new set of names (setLastname vs. setSurname).
Upvotes: 0
Reputation:
Your understanding is incorrect. dummyLabel
is the name of the property, and is not an alias for the instance variable - the instance variable is only called _dummyLabel
. So the following holds for an instance of Dummy
called myObject
:
[myObject dummyLabel]
worksmyObject.dummyLabel
works[myObject _dummyLabel]
failsmyObject._dummyLabel
failsmyObject->dummyLabel
failsmyObject->_dummyLabel
depends on the visibility of the ivar (@public
, @private
, @protected
)[myObject valueForKey: @"dummyLabel"]
works[myObject valueForKey: @"_dummyLabel"]
depends on the implementation of +accessInstanceVariablesDirectly
(i.e. it will work in the default case where +accessInstanceVariablesDirectly
returns YES
).Upvotes: 17