Joost Schuur
Joost Schuur

Reputation: 4482

Proper NSArray initialization for ivar data in a method

I'm new to Objective-C and iPhone development and have been using Apress' Beginning iPhone 3 Programming book as my main guide for a few weeks now. In a few cases as part of a viewDidLoad: method, ivars like a breadTypes NSArray are initialized like below, with an intermediate array defined and then ultimately set to the actual array like this:

NSArray *breadArray = [[NSArray alloc] initWithObjects:@"White", @"Whole Weat", @"Rye", @"Sourdough", @"Seven Grain", nil];
self.breadTypes = breadArray;
[breadArray release];

Why is it done this way, instead of simply like this:

self.breadTypes = [[NSArray alloc] initWithObjects:@"White", @"Whole Weat", @"Rye", @"Sourdough", @"Seven Grain", nil];

Both seem to work when I compile and run it. Is the 2nd method above not doing proper memory management? I assume initWithObjects: returns an array with a retain count of 1 and I eventually release breadTypes again in the dealloc: method, so that wraps things up nicely:

- (void)dealloc {
   ...
   [breadTypes release];
   [super dealloc];
}   

The setter is defined via a standard property (and eventual synthesize) directive:

@property (nonatomic, retain) NSArray *breadTypes;

Upvotes: 2

Views: 1052

Answers (2)

Georg Schölly
Georg Schölly

Reputation: 126155

In your second version, there's a memory leak. breadTypes is never going to be released.

Either use the version Laurent Etiemble suggested:

self.breadTypes = [NSArray arrayWithObjects:@"White", @"Whole Weat", nil];

(Many classes provide such convenience constructors. (That means all +classWithSomething:)

In the case of having no such constructor, you could use the alloc, init, autorelease technique:

self.breadTypes = [[[NSArray alloc] initWithObjects:@"White", nil] autorelease];

Of course this uses a little bit more memory and some CPU time, but for most applications it just doesn't matter and you cannot forget to include [obj release], which is the most common reason for memory leaks.

I believe though, Apple recommends not to use autorelease on the iPhone, but as I said, for most cases this won't matter.

Upvotes: 0

Laurent Etiemble
Laurent Etiemble

Reputation: 27909

The second way indeed may lead to memory leak; you explicitly create an array (taking the ownership), but you are not releasing it.

The best way to mix create and assignation is to use the class constructors (See NSArray reference). When invoking class constructor, you do not take ownership of the object, so there is memory leaks:

self.breadTypes = [NSArray arrayWithObjects:@"White", @"Whole Weat", @"Rye", @"Sourdough", @"Seven Grain", nil];

Upvotes: 4

Related Questions