views:

58

answers:

2

Ok heres the situation. I have a View controller class that serves as the main view(MainView). It contains a subview that another view controller takes care of(ChangingView). Now, every four seconds, ChangingView needs to change its view. What I am currently doing goes something like this.

ChangingView = [[AnotherView alloc] initWithNibName:@"AnotherView" bundle:[NSBundle mainBundle]];
[MainView addSubview:ChangingView.view]; 

Now, after the 4 seconds is up and before the lines up there are called I do the following.

[ChangingView release];
[ChangingView.view removeFromSuperview];

What is happening is I am getting memory warnings like mad. And eventually it gives me the debug messages of "program sent '0'" or "data formatters currently unavailable". Both of which I believe mean I am out of memory. I don't think that should be happening as the amount of stuff in the views isn't multiple MB so for some reason it has to be stacking or something. If you need any clarification please ask and any help will be greatly appreciated as I am currently stumped. Thanks in advance.

A: 

(I had originally said no, but I missed the fact the release happened later and he was saving the view controller reference).

If you are seeing memory use climb, be sure the views you are adding as subviews are really released... this is also a time when it would be a good idea to use Instruments to try and follow what was being allocated and deallocated.

Kendall Helmstetter Gelner
I posted a comment up above to further explain what it is I am trying to do. I can't have only one instance of the view controller as the class that it inherits from is a view controller itself.
Midnight
Hold on to every instance of the view controller you make. You can hold them in an NSArray if they need to be dynamic in number... but you can't let them autorelease and you can't retain them without keeping a reference.
Kendall Helmstetter Gelner
He's not throwing away the ViewControllers at all. If the code up there is correct, he's removing the views as well, so when the viewcontroller is thrown out, the view is also thrown out.
David Liu
Ok, I missed the part about the release and remove happening four seconds later (or perhaps there was some editing from when I first saw it??). I'm going to totally revise my response now, so anyone reading ignore the comments above this one...
Kendall Helmstetter Gelner
A: 

Something irks me about these two lines of code:

[ChangingView release];
[ChangingView.view removeFromSuperview];

I think that the very fact that you can actually access ChangingView.view after you've released without getting an EXC_BAD_ACCESS error means that you're not correctly releasing ChangingView everywhere (which, by the way, you should probably call ChangingView*Controller* so as not to confuse people whether it's a subclass of UIView or UIViewController).

Check whether ChangingView's dealloc method is actually ever called. Ever. There's not enough information or code to tell you where you're forgetting to release it, but I'm betting that's where the problem is at.

David Liu
well, those two lines of code in my code are not in that order. removeFromSuperview is called before the release. I release just before I set the variable to a new instance. I did what you asked and it does indeed hit every dealloc. Leaks tool shows no leaks but for some reason the memory just climbs. No idea why as I am releasing both the variable itself and also removing the view so to me it seems like there should be nothing left over.
Midnight
If you're calling them in the other order, then why are they listed in that order?View hierarchies don't appear as leaks in Leaks, because subviews maintain a reference to their parent, and Leaks does fairly dumb leak-detection which thinks that cyclic structures aren't leak. If you have IBOutlets, failing to release them in dealloc is an easy way to have a leak that Leaks doesn't catch - generally you should use properties and do `self.myOutletThingy = nil`
tc.
So if I created an IBOutlet variable (ex. IBOutlet UIImageView *bkgd) then in the dealloc I need to put bkgd = nil?
Midnight
`self.bkgd = nil` (note the **self.** which uses the property method and will release it), but yes.
David Liu
oh crap. I don't think I made them properties. If I didn't make them properties and go back and remake everything properties do I need to replace everything with self.etc for example my var ChangingView. would i now do [self.ChangingView release], self.ChangingView.view, etc?
Midnight
Well, you don't need to make them properties at all. They'll work just fine without being properties; you just won't have the helper code that will automatically release an object when you do `self.myObject = nil`. Also, if you do turn them into properties, you can still directly access your ivars directly without the `self.` in front. For right now, I probably suggest that you don't deal with properties if you can help it, since it gives you a fair bit of automated code that would probably take longer than this comment box to explain.
David Liu
so, if I don't have them set as properties, how do I make sure I am correctly releasing my IBOutlets? [MyOutlet release];MyOutlet = nil; is that what needs to be done?
Midnight
Yes, that is correct. You should put such a pair of statements, **for each** instance variable you retain, in your dealloc method (before [super dealloc]).
David Liu