问题
OK, this must have been asked before but I looked like mad and found nothing:
I have a simple array in my iphone app which I define like so:
@property (nonatomic, strong) NSArray *pages;
@synthesize pages = _pages;
I've seen this in Apples sample code and thought this is a nice short-cut for writing self.pages (i.e. _pages replaces self.pages) like so:
_pages = [[NSArray alloc] init];
but then Apple has this again (not exactly like this, but it appears as if they keep swapping randomly):
self.pages = [NSKeyedUnarchiver unarchiveObjectWithData:contents];
And finally:
[_pages release];
Which totally confuses me. What would be the difference between _pages and self.pages?
Thanks for your help.
回答1:
_pages
is the name of the object's ivar. pages
is the property name which is different.
So, @synthesize pages = _pages;
finally tells that pages
is the property for the ivar _pages
.
You will encouter the ivar direct access via _pages
in initializers and dealloc methods. Every where else, the property name is used to get/set its value.
回答2:
When you use a simple assignation :
_pages = ...
you simply set the instance variable.
When you use a property assignation :
self.pages = ...
It call a method synthesized automatically by the compiler (or defined by you) and for synthesizing this method, it checks the type of the property (retain, assign, ...) and writes code to match this type of property.
回答3:
This difference comes from common naming and usage practices.
Both the instance variable and the property refer to the same object. The difference in naming is used for pointing out the difference between the ivar (_pages
) and the property (pages
).
The ivar is owned by the instances of the class and it's up to them to handle ownership operations for it (alloc, retain, release, etc.). Typically, these ownership operations take place in init
and dealloc
.
On the other hand, the property provides the 'designated' access point for the ivar. The property methods (the setter and getter) may perform additional operations required for the proper management of the ivar. So accessing the ivar directly (as a usage pattern) is not recommended, even within the owning objects. For example, a setter might be implemented like this:
- (void) setPages:(NSArray *)newValue {
[newValue retain];
// additional operations that you will miss if you use the ivar
[someObject someUsefulOperationThatIsReallyNeeded];
[pages release];
_pages = newValue;
}
回答4:
_pages
is the instance variable and pages
is the property name. The property is accessed via the getter and setter methods pages
and setPages:
object.pages
is equivalent to [object pages]
or for your example `[self setPages:[NSKeyedUnarchiver unarchiveObjectWithData:contents]];
So the only actual object is the instance variable _pages
and so only this can be memory managed.
The property and synthesiser code in effect give the same as this code (in practice there could be extra code for memory management and thread locking
@interface MyClass
{
...
NSArray *_pages
}
- (NSArray*)pages;
- (void)setPages:(NSArray*)newValue;
@end
@implementation MyClass
- (NSArray*)pages
{
return _pages;
}
- (void)setPages:(NSArray*)newValue
{
_pages = newValue; // Note in non ARC code there would be some memort managment here
}
@end
回答5:
You can reference an @synthesized
property either as instanceVariableName
or as self.propertyName
. The two names can be the same or different.
When you reference as instanceVariableName
, and modify the value, none of the retain/copy logic of the associated property is applied -- you're just referencing the "raw" variable. When you reference self.propertyName
, the retain/copy logic is applied, and, eg, if the property is declared with "retain" then the old value will be released and the new value retained.
When assigning an already-retained value (such as one from alloc/init) to a property, it's simpler (if this an initialization where the property was previously nil
) to assign to instanceVariableName
and skip the need to release
the value (so that the net number of retains
will be 1 at the end of the operation). But when assigning a value that is not retained
(other than an autoreleased
retain
) to a property, you want to have the property's retain
occur, so you'd use the self.propertyName
notation.
Using a leading "_" for an instance variable that is also a property is a simple convention to keep these two apart, and avoid accidentally referencing one (by adding/removing self
erroneously) when you meant the other.
来源:https://stackoverflow.com/questions/8545363/objective-c-variable