I have two scenario for the project with ARC and project without ARC.
1) The project without ARC.we can use the following.
MyViewController* viewController = [[MyViewController alloc] init];
[self.navigationController pushViewController:viewController animated:YES];
[viewController release];
2)How can I achieve the above in the project which is with ARC.
a)where can I allocate memory?
b)where can I release viewcontroller after pushing?
c)is there any standard for it?
When using ARC you do not need to release the viewController, the compiler will add the release and retain for you..
So in ARC this will do:
MyViewController* viewController = [[MyViewController alloc] init];
[self.navigationController pushViewController:viewController animated:YES];
Using retain, release and autorelease will result in a compiler error.
Be aware that you will need to use the #property correctly when using ARC. Use strong for properties that you want to retain and weak for properties that you just want to assign. If you want iOS 4.3 support you can't use weak but should use unsafe_unretained.
In ARC you don't user release, autorelease or retain. ARC does that for you. You simply allocate it as usual with [[Class alloc] init]; but you don't need to send the above messages to your object.
The pushing of the view controller with the ARC enabled is very simple:
MyViewController* viewController = [[MyViewController alloc] init];
[self.navigationController pushViewController:viewController animated:YES];
This is because ARC automatically counts the active pointers to the allocated objects, and when the there are no active pointer to the object, the object is automatically released for you. So you don't have to call those methods yourself.
MyViewController* viewController = [[MyViewController alloc] init];
[self.navigationController pushViewController:viewController animated:YES];
Thats it only if you are using ARC, no need to release the viewcontroller after pushing, as ARC takes care of all releases and it inserts itself all the releases at compile time only, so it will work fine.
Related
Please see below sample . Every thing works but memory is not released. Here MYTest is not getting released and memory seems to be increasing when watched in instruments tool
- (IBAction)methodXYZ:(id)sender
{
MYTest * myTest = [[MYTest alloc]initWithNibName:#"myNib" bundle:nil];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController: myTest];
[self presentModalViewController:navigationController animated:YES];
}
}
and in myTest when finished i call
[self dismissModalViewControllerAnimated:YES];
i also tried setting delegate and dismissing from parent , but that also doesnt solve the issue ..
Any help will be greatly appreciated.
Thanks
mia
If ARC is enabled (be sure it is) you dont need to worry about it, the system will dealloc the memory when it's necessary.
In the other hand, I invite you to take a look at the classic way (non ARC), its useful sometimes if you want to have a control of the memory like it seems you want.
I have this same piece of code in two different parts of my app.
In one section it is executed perfectly, and in the other it is completely ignored. I've put in a breakpoint and watched the program go through each line of this code without loading the next xib/class it is supposed to.
Here is the code:
UIViewController *nextController = [[ClassNameViewController alloc] initWithNibName:#"MatchingView" bundle:nil];
[nextController performSelector:#selector(setDelegate:) withObject:self];
[self presentModalViewController:nextController animated:YES];
Any ideas why this might be getting ignored and not presenting my viewController?
Try using ..
[self.navigationController presentModalViewController:nextController animated:YES];
I had this code in viewDidLoad and moving it to viewDidAppear made it work.
-(IBAction) btnLoginPressed{
Login *loginOverView = [[Login alloc] initWithNibName:#"Login" bundle:nil];
[self.navigationController pushViewController:loginOverView animated:YES];
[loginOverView release];
}
loginOverView will never get released?
Why do you think it will never get released?
You have done the right thing by balancing the init with a release.
(in the second line the navigationController does retain login but it will release it itself when it is necessary)
You have released the object which you have taken ownership of through alloc or new. So according to the Memory Management guidelines you must release it. So you have done the right thing.
I'm having a strange problem with my UINavigationController. the stacktraces are:
which is very odd to me because all I did was:
CommonVC* cvc = [[CommonVC alloc] init];
//CommonVC is my customized viewController. and i did some setting after the init.
[self.navigationController pushViewController:cvc animated:TRUE];
[cvc release];
and after 3 times pushing and popping it crashes.
i also ran it with NSZombie but it told the zombie is the CommonVC itself.
so can anyone help me find where the problem would be?
Do you make use of delegates and set them in your view controller. If yes check if they are made nil...
I have a app which uses two UINavigationControllers - one for the menu system and one for the actual game. A common UINavigationController is declared in my appDelegate. When the app loads, it either loads the Menu or the Game's UINavigationController. And of course the player can then navigate between the two.
When going from the menu to the game, I create a new UINavigationController and present it as follows:
GameViewController *rootController = [[GameViewController alloc] init];
UINavigationController *newNavController = [[UINavigationController alloc] initWithRootViewController:rootController];
[rootController release];
newNavController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:newNavController animated:YES];
[newNavController release];
However, I've noticed that when I do this, the Menu's viewController never calls dealloc. Presumably because there's still a reference to something keeping it alive. I've found that when I explicitly set the App Delegate's UINavigationController to the new navigation controller, (before releasing the new navController) it releases the Menu. I do this as follows:
MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
appDelegate.navController = newNavController;
[newNavController release];
Is this good practice? I've found that when navigating from the game back to the menu however, the same trick doesn't seem to work. I.e.
MainMenuViewController *menuViewController = [[MainMenuViewController alloc] init];
UINavigationController *newNavController = [[UINavigationController alloc] initWithRootViewController:menuViewController];
[menuViewController release];
newNavController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:newNavController animated:YES];
//Setting the appDelegate's navController to the new navController allows the menu to dealloc.
//This must happen AFTER the newNavController has been loaded.
MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
appDelegate.navController = newNavController;
[newNavController release];
never call's dealloc on the game's main ViewController. And when I navigate back to the game again, the menu's main ViewController is no longer released either.
Am I missing something when juggling UINavigationControllers?
Thank you,
Michael
EDIT: I've since realised that the reason my game's main ViewController was not deallocing, was because I has some NSTimers that I hadn't invalidated! However, I'm still curious to know if my above approach is correct, and that explicitly redefining the navController in the App Delegate is the correct way to allow the different UINavigationControllers to dealloc :)
Make your life easier. Use a single UINavigationController, and maintain two separate View Controller stacks, which are just arrays of UIViewControllers. You can use [UINavigationController setViewControllers:animated:] to just swap the stacks out and leave the nav controller in place. Use UINavigationController.viewControllers to get the current stack to hold onto before replacing it. It's something like 14.3 billion times easier and cleaner than dealing with all the vagaries of multiple nav controllers.