I have this code in my app and it says memory leak at 'gvc'.
GameViewController* gvc = [[GameViewController alloc] init];
[self.navigationController pushViewController:gvc animated:YES];
If i modify this code to autorelease view controller, it crashes my app after a while giving error 'Missed Method'
GameViewController* gvc = [[[GameViewController alloc] init] autorelease];
[self.navigationController pushViewController:gvc animated:YES];
Is there something wrong with autorelease? How to resolve this memory leak?
Thanks in advance.
You can safely do this:
GameViewController* gvc = [[[GameViewController alloc] init] autorelease];
[self.navigationController pushViewController:gvc animated:YES];
or this:
GameViewController* gvc = [[GameViewController alloc] init];
[self.navigationController pushViewController:gvc animated:YES];
[gvc release];
They are functionally equivalent and don't cause memory leaks or crashes. Look at your code after [self.navigationController pushViewController:gvc animated:YES]; to see if you over-release gvc.
Just release it when you're all done. If you need it all the time, then put GameViewController *gvc; in the header and put [gvc release]; in the dealloc method.
The obvious solution is simply to release the view controller once you've pushed it onto the nav controller.
i.e.:
GameViewController* gvc = [[GameViewController alloc] init];
[self.navigationController pushViewController:gvc animated:YES];
[gvc release];
That said, I'd be surprised if the autorelease was actually causing a memory leak at all.
It may be everything. I mean, your first code is obviously leaking, and the second code snippet is ok at first glance, but we don't know what you implement inside that class. Imagine in GameViewController, you have a string property userName, and in its dealloc, you do something like:
- (void)dealloc
{
[userName release];
[userName release];
[super dealloc];
}
Then of course it crashes when you release the controller. You should use gdb backtrace (type "bt" when it crashes) to see exactly where it crashes, or better yet, try to enable NSZombie and use instruments to find out.
Btw as a rule of thumbs in iPhone/iPad programming (where resources are scarce), try to avoid autorelease whenever you can.
Related
Even though I release the results object using autorelease, the Leak tool it is showing 100% leak in leak instrument.
ResultsViewController *results = [[[ResultsViewController alloc]initWithNibName:
#"ResultsViewController1" bundle:nil] autorelease];
[results getscore:(int)score:(int)skippedwords:(int)crtwords];
[self.navigationController pushViewController:results animated:YES];
In "Instruments" it always show you the autoreleased objects as "leaks"
Do one thing alloc/release "results" by yourself. Never ever use "Autorelease" until unless you have to return the object to other class or method.
ResultsViewController *results = [[ResultsViewController alloc]initWithNibName: #"ResultsViewController1" bundle:nil];
[results getscore:score :skippedwords :crtwords];
[self.navigationController pushViewController:results animated:YES];
[results release];
Because you have already pushed this controller to navigation controller so you don't need its instance anymore. Happy Coding ;)
I have a strange problem with a method is called each time a button is pressed:
- (void)launcherView:(TTLauncherView*)lnchr didSelectItem:(TTLauncherItem*)itm {
MyObject* obj = ...
MyViewController* detailView = [[MyViewController alloc] init]; // line A
[self.navigationController pushViewController:detailView animated:YES];
[detailView setObject:obj];
detailView = nil; // should I also release it? -- line B
}
The problem is that I apologize I have to release detailView (memory tool shows me I have a memory leak is it is not done), also because navigationController should retain my detailView, but both if I try to add autorelease in line "A" or in line "B", or simply a release for detailView in line "B" (of course before assigning it nil), the program crashes with an EXC_BAD_ACCESS 'cause release message sent to deallocated instance [CALayer]...
Any idea?
Thanks a lot
try it this way
- (void)launcherView:(TTLauncherView*)lnchr didSelectItem:(TTLauncherItem*)itm {
MyObject* obj = ...
MyViewController* detailView = [[MyViewController alloc] init];
[detailView setObject:obj];
[self.navigationController pushViewController:detailView animated:YES];
[detailView release];
detailView = nil; // now this will be optional
}
Does this work without crashing?
- (void)launcherView:(TTLauncherView*)lnchr didSelectItem:(TTLauncherItem*)itm {
MyObject* obj = ...
MyViewController* detailView = [[MyViewController alloc] init];
[self.navigationController pushViewController:detailView animated:YES];
//[detailView setObject:obj]; // <- What's this for?
[detailView release]
}
try "initwithnibname"
unrelated but if you chase memory leaks don't forget to release MyObject
When you set detailView = nil; without releasing it, you only nil the pointer to the memory. The block of memory is still allocated until you release it.
You must use [detailView release] before detailView = nil or else you will have no way to reference that block of memory again (memory leak).
I am struggling to find out if pushViewController retains the controller, currently I have the following code (which works) ...
ColorController *colorController = [[ColorController alloc] initWithNibName:nibColor bundle:nil];
[[self navigationController] pushViewController:colorController animated:YES];
[colorController release];
but am considering removing the release and adding an autorelease ...
ColorController *colorController = [[[ColorController alloc] initWithNibName:nibColor bundle:nil] autorelease];
[[self navigationController] pushViewController:colorController animated:YES];
Much appreciated
Gary
This does nothing...
ColorController *colorController = [[ColorController alloc] initWithNibName:nibColor bundle:nil];
[[[self navigationController] pushViewController:colorController animated:YES] autorelease];
You are autoreleasing the return value of pushViewController:animated:, which is void.
Your first snippet is valid, and correct. pushViewController: does indeed retain the controller that is pushed.
Edit: In your updated code, there is little difference between the two samples. Both maintain proper retain counts. However, it is a "best practice" to avoid using autoRelease unless necessary (especially in a memory sensitive area, like the iPhone). This helps your application to maintain a more predictable and manageable memory footprint.
Yes, the view controller is retained.
There isn't a huge difference between the two code blocks you posted (at least the version I'm looking at -- other people probably saw an earlier version with a misplaced call to autorelease). You could use either one. It's a matter of style.
It sure does. Anytime you give one object to another SDK object like this, it will be retained. Though that second line isn't autoreleasing what you think. Usually you want the autorelease on the same line as the init for clarity sake.
ColorController *colorController = [[[ColorController alloc] initWithNibName:nibColor bundle:nil] autorelease];
[[self navigationController] pushViewController:colorController animated:YES];
If want to try, you should try this
id temp = [self.navigationController.viewControllers objectAtIndex:1];
[self.navigationController popToViewController:temp animated:YES];
you'll be navigated to any other previous ViewController that are available in the stack.
I encountered some strange memory leaks executing following code on iPhone device:
#implementation TestViewController
#synthesize myButton;
- (IBAction)buttonPressed {
ABPeoplePickerNavigationController* selectContactViewController = nil;
selectContactViewController = [[ABPeoplePickerNavigationController alloc] init];
selectContactViewController.peoplePickerDelegate = self;
[self presentModalViewController:selectContactViewController animated:YES];
[selectContactViewController release];
}
Releasing the picker simple done as follows:
- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker {
[self dismissModalViewControllerAnimated:YES];
}
Instruments marks "selectContactViewController = [[ABPeoplePickerNavigationController alloc] init];" as leaking. Any idea why?
You might want to construct your Picker control like so:
ABPeoplePickerNavigationController* selectContactViewController = nil;
selectContactViewController = [[[ABPeoplePickerNavigationController alloc] init] autorelease];
selectContactViewController.peoplePickerDelegate = self;
[self presentModalViewController:selectContactViewController animated:YES];
When you present the modal view controller, it will retain the view on its own. That's how it's able to still pass you an instance of the view controller to your delegate. Best bet is to set the view controller to be autoreleased, so when it gets popped from the navigation controller, the NSAutoReleasePool will garbage collect it.
Just a comment - do you use any protocol like UINavigationControllerDelegate in the interface declaration?
I encountered a situation where just referencing this protocol caused a similar leak message.
i am trying to launch a view from a button. When I do it causes a memory link but I can see why.
CamViewController *dvController = [[CamViewController alloc] initWithNibName:#"Cam_View" bundle:[NSBundle mainBundle]];
dvController.camType = 1;
[self.navigationController pushViewController:dvController animated:YES];
[dvController release];
any ideas?
The problem is most likely in your CamViewController implementation. If I were to guess, you are creating a bunch of objects in your xib file and they are not getting released in the Controllers dealloc.
It is important to remember that you are responsible for releasing your IBOutlet attached objects in your class.