views:

41

answers:

1

Please, take a look at my code bellow. This part pops top view controller (usually, the same ArticleControllerController) from the stack (I found that the problem stays the same no matter if I pop single controller or pop to the root controller), creates new one and adds to the stack.

The problem is, that its retain count never goes to zero and so dealloc method of ArticleControllerController is never called leaving large amounts of various interface objects unreleased. Eventually app crashes (at least in device and at least I think this part is the main problem) because of low memory.

- (void) navigateToNewsCategoryByIndex:(int)idx {
    [app.nav popViewControllerAnimated:NO]; // could be popToRootController
    ArticleControllerController *ac = [[ArticleControllerController alloc] init];
    ac.categoryIndex = idx;
    [app.nav pushViewController:ac animated:NO];
    [ac release];
    NSLog(@"AC retain count: %d", [ac retainCount]); // prints 2
} 

So, I guess, popViewControllerAnimated releases only one of the remaining two retains. Why? What should I look for? What can I do? Call [ac release] two times (that would be terrible thing)?

+1  A: 

How do you know that a retain count of 2 isn't correct behavior for a navigation controller?

You can't rely on retainCount to do alloc / release debugging because we don't know how the internals of the UIKit work. As long as you retain and release correctly inside your code you can be 99.9% sure that UIKit will also be working correctly.

I would guess that popViewController will remove all the retains that pushViewController added - even though I don't know how many that would be - but it might set it to be autoreleased so you can't guarantee that it will be released immediately after a call to popViewController.

I'd work on the assumption that the UIKit navigation controller doesn't have a bug (otherwise lots of other developers would be complaining about it!) and somewhere in your code you're retaining it somewhere else (probably without realising it i.e. a delegate property declared to retain instead of assign etc)

Hope that helps!

deanWombourne
Retaining delegates was exactly my problem. After I posted my question I decided to add my own retain/release methods and print retainCounts in them, so after they showed even more crazy numbers and "retains" adding up after some time I figured out that it was because stupid me somehow added retain instead assign to delegate property. Damn, now I'd like to cut my finger yakuza style...
sniurkst
We've all done it :)
deanWombourne
Ah, unfortunately I'm still getting memory warnings and crashes and s till have no bright idea why... Well, at least that delegate part is fixed now. (Edit: hah, looks like I did it everywhere - there's still hope!)
sniurkst
`egrep -rni 'retain.*delegate' *` should help ;)
deanWombourne
But could be a reason to actually use "retain" instead of "assign" here? I changed them all and now my application crashes because some of [self.delegate ...] calls are sent to wrong object (not the assigned delegate).
sniurkst
If you really need to retain a delegate, you must remember to set the delegate to nil before you call release on the object, otherwise it's retain count will never go down to 0.
deanWombourne