1

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.

n.evermind
  • 11,944
  • 19
  • 78
  • 122
  • 1
    This is indeed a multiplicate: http://stackoverflow.com/q/3521254/ http://stackoverflow.com/q/7174277/ http://stackoverflow.com/q/5466496/ http://stackoverflow.com/q/6049269/ http://stackoverflow.com/q/822487 http://stackoverflow.com/q/2371489/ http://stackoverflow.com/q/5582448/ and [more](http://stackoverflow.com/search?q=%5Bobjc%5D+synthesize+underscore&submit=search). – jscs Dec 18 '11 at 07:35

5 Answers5

5

_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.

  • 3
    Well said. Note that [Apple reserves names prefixed with an underscore](http://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/NamingBasics.html#//apple_ref/doc/uid/20001281-1002931-BBCFHEAB), and non-Apple developers should avoid using an underscore prefix in order to avoid name collisions. One solution, if you want to differentiate your ivars from property names, is to use an underscore suffix instead: `foo_` instead of `_foo`. – Caleb Dec 17 '11 at 14:40
  • 2
    @Caleb -- Actually, Apple only reserves the underscore for use in *method* names, according to that writeup. – Hot Licks Dec 17 '11 at 15:00
  • @HotLicks That's a fair point. And it makes sense -- ivars can be made private, and the compiler should warn if you try to redefine one anyway. Not so with methods. – Caleb Dec 17 '11 at 15:39
  • Hm... I'm still confused. To start getting my head around this: Can I just start with NOT using _pages at all? When I do really have to use this? In all the sample apps I've seen (those in text books for beginners), they never use ivars. I guess they have a reason, not? – n.evermind Dec 17 '11 at 19:16
  • Good reasons yes. You can avoid using `_` as well as you can define an ivar called `foo` and define a property on it called `bar`. I suggest you read [this](http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/objectiveC/Chapters/ocProperties.html#//apple_ref/doc/uid/TP30001163-CH17-SW1) too. –  Dec 17 '11 at 19:24
  • @n.evermind -- I explained the difference pretty well in my post, though Caleb doesn't like it. – Hot Licks Dec 17 '11 at 20:08
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.

Johnmph
  • 3,391
  • 24
  • 32
2

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;
}
Nick Toumpelis
  • 2,717
  • 22
  • 38
1

_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
mmmmmm
  • 32,227
  • 27
  • 88
  • 117
-1

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.

Hot Licks
  • 47,103
  • 17
  • 93
  • 151
  • 3
    This is confusing in the extreme. You access a property by calling the property accessor methods, or by doing something that calls them (such as using dot syntax or key value coding). The accessor methods *define* the property. If a property is backed by an instance variable, then it may also be possible to access that ivar directly, but that's not the same as accessing the property. The 3rd paragraph is beyond confusing and largely incorrect: we assign directly to ivars in initializers for safety, not for simplicity. – Caleb Dec 17 '11 at 14:48
  • It's confusing no matter how you describe it. The important thing to know is that `instanceVariableName` and `self.propertyName` (for `@synthesized` properties) yield the same values on read, but assigning to them produces significantly different semantics. – Hot Licks Dec 17 '11 at 14:53
  • 1
    It doesn't have to be that confusing. Access properties, not ivars, except in initializers and `-dealloc`. – Caleb Dec 17 '11 at 15:06
  • @Caleb -- That doesn't answer the question. And I've come to favor doing `self.propertyName = nil;` in `-dealloc`. – Hot Licks Dec 17 '11 at 20:06