views:

113

answers:

3

[I'm sure this is not odd at all, but I need just a bit of help]

I have two retain properties

@property (nonatomic, retain) NSArray *listContent;
@property (nonatomic, retain) NSArray *filteredListContent;

and in the viewDidLoad method I set the second equal to the first (so now the retainCount is two, I think):

self.filteredListContent = self.listContent;

and then on every search I do this

 self.filteredListContent  = [listContent filteredArrayUsingPredicate:predicate];

I thought I should do a release right above this assignment -- since the property should cause an extra retain, right? -- but that causes the program to explode the second time I run the search method. The retain counts (without the extra release) are 2 the first time I come into the search method, and 1 each subsequent time (which is what I expected, unfortunately).

Some guidance would help, thanks! Is it correct to not release?

+2  A: 

No, you do not need to make a retain call prior to running the filter search. Any old value in the property will be released.

The first time you check the retain count, self.filteredListContent and self.listContent reference the same array object and both have a reference counter for that array. After the search self.listContent's retain count drops to 1 because it was released by self.filteredListContent when the search results were set (and subsequently retained).

Daniel Johnson
Excellent, that makes perfect sense.
Yar
+3  A: 

You don't have to release it, that's correct.

Because the variable is stored in two locations, its retain count should be 2. Here's the reason it crashes. (Retain count of self.listContent in brackets.)

self.listContent = someArray                [1]
self.filteredListContent = self.listContent [2]
[self.filteredListContent release]          [1]

self.filteredListContent = somethingElse    [0] -> deallocation of listContent
[self.listContent doSomething]              [whoops, bad things happen]

self.listContent gets deallocated too early. If you don't use [... release]it the retain count math works.

Read Vincent Gable's blog for a really short summary on when to use release. (Interestingly, this blog post was inspired by Andiih's answer on Stackoverflow.)

Georg
I think you mean [self.filteredlistContent release] in line 3, but otherwise good explanation
h4xxr
Isn't that blog article arguing for using `autorelease` more often than other people would recommend it?
Yar
@yar: Are you aware that `self.filteredListContent` is equal to `self.listContent` and `someArray` in that line? It just doesn't matter which one is released, it's all the same object. (This of course is only true if the property isn't a copy property.)
Georg
@yar: On a Mac I agree 100% with Vincent Gable, the performance/memory penalty is of no concern there. On the iPhone, using autorelease _might_ make a difference. But if you care about that, you shouldn't use properties, those use autorelease too.
Georg
@Georg, sorry I had missed that comment above. Yes, I am aware that the line does the same thing regardless of which of the two of its names you use, since the release operates on the, um, thing the variable points to, not the variable itself.
Yar
+2  A: 

If you didn't NARC* the object, you don't need to release it.

*NARC -- New, Alloc, Retain, Copy

A retained property both retains the new value on assignment and releases the old value when that happens.

bbum
Thanks, my error is clear now, I had forgotten that a `retain` property is basically doing a retain when it gets it and a release when it gets a new one.
Yar
You mean "new alloc retain copy"!
Yar
Correct you are! Fixed!
bbum