views:

124

answers:

2

Hi

I have been developing an app for a while and now I have gotten to the "Instruments-Leaks" part.

I remember a thing that puzzled me about ivars a few months back when I was learning. I took the whole thing a bit on faith and just followed the way Apple and others did it. As far as I can read, the accessors generated by the SDK will take care of the memory management.

But how are ivars themselves initialized?

If I have an ivar like this in my interface;

@interface
    {   
    NSArray *results;
    }

    @property(nonatomic, retain) NSArray *results;
    @end

@implementation
@synthesize results;

If I during run time try to do this:

[self setResults:allReadyInitializedArray];

It will crash, telling me that this result object was not initialized. If I however do this:

self.results = [[NSArray alloc] init]; //Im assigning this property memory, but hasn't the SDK already done that?
[self setResults:allReadyInitializedArray];

it will work but it will apparently leak memory.

I was under the impression that using the generated accessors would release the old value before setting the new, meaning the above ought to come out with the old value released and the new with a +1 retain count.

Does it specifically have to do with the ivar being of type NSArray/NSMutableArray, I can't recall it has been a problem with other ivars.

The problem has been particular prominent in my XML parser, where I continuously need to set an ivar value, use it, overwrite this value, use the new value etc.

Would someone please help me outline the correct way "of going from": @property() -> @synthesize -> using the ivar -> to dealloc?

I have read the memory management documents, I have tried looking for some in debt documentation that was within my understanding, but it seems that even though I use ivars on a daily basis I don't understand what goes on behind the scenes.

+2  A: 

All ivars initially set to nil so you need to instantiate them before use. It is really hard to say why setResults may produce errors without seeing its implementation.

self.results = [[NSArray alloc] init];

Here you create new array object using alloc method - its retain count equals 1. After that your setter method retains your array once more and so your 1st objects retain remains "unhandled" resulting in memory leak. To remove leak you can rewrite your code like:

self.results = [[[NSArray alloc] init] autorelease];
// or
self.results = [NSArray arrayWith...]; // any NSArray's convenience method that returns autoreleased object.  
Vladimir
A: 

My understanding is that

self.results = anArray;

is the same as

[self setResults:anArray];

just because results is a property in this case.

The way setResults: is implemented is set by the @property (in this case it will retain the new value). So this means anArray will have a retain count of 1. After setting self.results, anArray will have a retain count of 2. This is why you want to release the previously used anArray. That said, I don't understand why setResults: crashes when you're setting it. (Maybe it just crashes only when you try to use self.results, instead of setting it?) I'm just a beginner myself, if something is wrong I strongly encourage everyone who reads this to let me know what is wrong or correct. Still learning this myself.

The way Apple would do this:

In the .h file

@property (nonatomic, retain) NSArray *results

In the .m file

@synthesize results;

- (id)init {
    NSArray *anArray = [[NSArray alloc] init];    // retainCount = 1
    self.results = anArray;                       // retainCount = 2
    [anArray release];                            // retainCount = 1, only one "left" is in self.results
}

- (void)dealloc {
    [results release];
}
bddckr
Hi CrisB.I found this write up extremely useful:http://www.iphonedevsdk.com/forum/iphone-sdk-tutorials/7295-getters-setters-properties-newbie.htmlI did a regexp ( self.* = \[\[.* alloc\] ) for every instance in my code where I don't do as you and Apple describe above. (there where around 120 instances!)I then went through all the code again and marked the occurrence of actions like:"arrayWithArray" and marked them //autorelease.lastly I moved every dealloc method up under the @synthesize, to easier keep track of everything.All this gave me a much better understanding of ivars. Thanks
RickiG