iOS view controller memory not released after it's been dismissed - ios

When the user clicks a button it presents a new tab bar view controller with two view controllers. Here's how I do that
ACLevelDownloadController *dvc = [[ACLevelDownloadController alloc] initWithNibName:#"ACLevelDownloadController" bundle:[NSBundle mainBundle]];
ACInstalledLevelsController *ivc = [[ACInstalledLevelsController alloc] initWithNibName:#"ACInstalledLevelsController" bundle:[NSBundle mainBundle]];
UITabBarController *control = [[UITabBarController alloc] init];
control.viewControllers = #[dvc, ivc];
dvc.tabBarItem = [[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemFeatured tag:0];
ivc.tabBarItem = [[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemDownloads tag:1];
[self presentViewController:control animated:YES completion:nil];
this works fine. I dismiss that view controller with a dismiss method in both the ACLevelDownloadController and ACInstalledLevelsController. That also works fine. What's strange is that the memory usage goes up when I present the view controller
but it never goes back down. If I present it again, it goes up even more
I'm using ARC. Why is the memory that the view controllers use not being released after they are dismissed?
EDIT
The way they are dismissed is both ACLevelDownloadController and ACInstalledLevelsController have IBActions hooked up that call this method when they are clicked
- (void)dismiss:(id)sender{
[self dismissViewControllerAnimated:YES completion:nil];
}

What we can observe from the memory usage graph is that the tabViewController is not being dismissed properly and it builds up in the stack. While dismissing you have to allow the viewController which presented the tabViewController to dismiss it. It is its responsibility to dismiss. Also keep weak references for Outlets and assign any strong references to nil** in viewWillDisapper: . You can present a viewController modally as a temporary interruption to obtain important information from the user. If its not the case here, you can remove presenting modally. Check this link. Hope this helps :)

Related

Trouble presenting view controller from within VC within UITabViewController

My app is built around a UITabBarController and within the first View Controller I am attempting to present a "settings view" for a user but for some reason if this settings view gets presented more than once all buttons stop functioning and the app shits down completely.
Within FirstViewController.m I have:
- (IBAction)showSettings:(id)sender
{
UIViewController *settingsView = [self.storyboard instantiateViewControllerWithIdentifier:#"SettingsViewController"];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:settingsView];
[self.navigationController presentViewController:nav animated:YES completion:nil];
}
which is attached to a UIButton labeled "settings".
Within SettingsViewController.m I have:
- (IBAction)done
{
NSLog(#"DONE");
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
}
which is attached to a UIButton labeled "done" in the top left corner of SettingsViewController.
The first time I press "settings" then "done" it works without a problem but if I ever press the "settings" button again the "done" button loses functionality completely (completely unclickable) and the user is forced to restart the app in order to continue using it.
My console prints this when the app loads which I believe outlines the problem:
Unbalanced calls to begin/end appearance transitions for
<UITabBarController: 0x7f97f5f1e780>
But if I try to make an instance of "TabBarController" and present the view that way I just get an error that I am attempting to present a VC not within the hierarchy...
I am just not sure what the appropriate way to present/dismiss a view controller within a UITabBarController is but as of right not my app is lacking basic functionality. I don't see why FirstViewController can't just present the view normally.
Any help is greatly appreciated, this is a very annoying Bug and I wasn't able to find a workable solution anywhere else online. Let me know if I should provide more info/code
Edit: Changed typo UITabViewController to UITabBarController
I don't understand why you are instantiating a Nav controller.
Simply show modally. it should work.
Do you need a "go back" look and feel?
If you already have a nav controller in your hierarchy you can push settings.
anyway: when you do:
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:settingsView];
[self.navigationController presentViewController:nav animated:YES completion:nil];
in first line you create a LOCAL variable
in second you use self. self.navigationController
1) who holds "nav"?
2) If you already have a nav controller (as self.navigationController shows.. or is NIL?) why use "nav"?
It seems you set the dismiss to the navigation controller and not the settings view controller. Try using self.dismiss instead of self.navigationcontroller.dismiss
You to define root view controller for navigation push and pop both
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) UINavigationController *navController;
self.navController = [[UINavigationController alloc] initWithRootViewController: objcReg];
self.navController.navigationBarHidden =YES;
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] ;
self.window.rootViewController = self.navController;
[self.window makeKeyAndVisible];
//[self.navigationController presentViewController:objectofViewCantroller animated:YES completion:NULL];
//[self.navigationController popViewControllerAnimated:YES];

Switching underlaying view controllers iOS 8

This is the goal :
I have a navigation controller (NC1), that is presenting modally some view controller (VC). When I do some action in that view controller, I need to (invisibly for the user) dismiss VC, dismiss NC1, then present another navigation controller (NC2) and present the same view controller VC.
In iOS 7.0, 7.1 this is working well via this (slightly adjusted) code:
[controller dismissViewControllerAnimated:NO completion:nil]; //dismiss VC
[self.presentedViewController dismissViewControllerAnimated:NO completion:nil]; //dismiss NC1
SomeViewController * someViewController = [[SomeViewController alloc] init]; // root vc for NC2
NavigationController * navigationController = [[NavigationController alloc] initWithRootViewController:someViewController]; //NC2
SomeViewController2 * someViewController2 = [[SomeViewController2 alloc] init];
[navigationController presentSomehow:someViewController2 animated:NO completion:nil]; //another pushed to NC2
[someViewController2 presentViewController:controller animated:NO completion:nil]; //present VC again
but in iOS 8 (Xcode 6.0) it seems that even after dismissing, VC remains active and the app crashes at the last line with:
Application tried to present modally an active controller ...
And of course if I move the code to completion blocks the changes are visible to user (and ugly).
Is there a way to check or force the VC to leave the active state, or some other way to simulate the iOS 7 behavior?
Thanks for answers!

UIPopover with UINavigationController and UITableView: tableView delegates not called

I am trying to display a simple iPad popover which contains a navigationController with a tableView.
popover -> navigation controller -> view controller -> table view.
I do need the navigationController because on touching the cells I want to push another viewController (within that same popover).
Without the navigation controller, everything is fine.
But as soon as I put the viewController inside a navigationController, the tableView stops responding (didSelectRow doesn't get called). I suppose something is wrong with my delegates but I just can't work it out.
. The navigationController responds fine (I can hit a button I have in the top bar)
. The buttons that are IN the cells respond fine.
. If I touch down and hold on a cell it gets highlighted, but not selected.
UPDATE: I just found out that if I hold the cell down for at least a second, the delegate is called when I release it. any less than that and it is never called...???
Here is the code use:
ModalViewController* controllerWithTable = [[self storyboard] instantiateViewControllerWithIdentifier:identifier];
UINavigationController* navigationController = [[UINavigationController alloc] initWithRootViewController:controllerWithTable];
UIPopoverController* popover = [[UIPopoverController alloc] initWithContentViewController:navigationController];
popover.delegate = self;
[popover presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
If you are using a popoverController to show a table view, you don't need to embed it in a navigation Controller, Instead make a different Viewcontroller with the table view and just shoe that inside a popover controller .I used it somewhat like this..
Make a global reference for UIPopoverController in your app delegate,
//in your Appdelegate.h file declare this
#property(strong, nonatomic) UIPopoverController *popOverForTableView;
Now In the controller which you want to show the PopOver view use this,
TableViewCOntroller* popoverContent = [[TableViewCOntroller alloc] init];
NSString *identifier=#"tableVC"
popoverContent =[[UIStoryboard storyboardWithName:#"Main"
bundle:nil]
instantiateViewControllerWithIdentifier:identifier];
popoverContent.preferredContentSize = CGSizeMake(330, 280);
AppDelegate *appDelegate=(AppDelegate *)[[UIApplication sharedApplication]delegate];
appDelegate. popOverForTableView = [[UIPopoverController alloc]initWithContentViewController:popoverContent];
appDelegate.popOverForTableView.delegate = self;
appDelegate.popOverForTableView.backgroundColor=[UIColor blackColor];
[appDelegate.popOverForTableView presentPopoverFromRect:self.date.frame inView:self.view permittedArrowDirections:(UIPopoverArrowDirectionUp) animated:YES];
You can dismiss it accordingly…,…see if this Helps..
Ok I found the answer there: https://stackoverflow.com/a/18159463/3562952
The tableView was not irresponsive, it was deceptively responding only after a 1-3 seconds hold down.
I had a tap responder on the parent view that was capturing the tap. I am now removing it when displaying the popover and putting back in on dismissal.
I was googling for the wrong symptoms :)

Dismiss UIViewController after presenting another one

I'm developing a single view iOS 5.0+ app and I'm going to navigate throw my ViewControllers this way:
SearchViewController* search =
[[SearchViewController alloc] initWithNibName:#"SearchViewController"
bundle:nil];
[self presentViewController:search
animated:NO
completion:nil];
My question is, if I'm opening SearchViewController from HomeViewController, is HomeViewController dismissed after SearchViewController is shown?
I have a lot of UIViewControllers and I don't know if all of them will be on memory while user is navigating between them.
If You want to Present Only one Viewcontroller you can try like,
SearchViewController* search =
[[SearchViewController alloc] initWithNibName:#"SearchViewController"
bundle:nil];
[self dismissViewControllerAnimated:NO completion:^{
[self presentViewController:search
animated:NO
completion:nil];
}];
When you present a ViewController from another ViewController, they never get released from memory. To release them from memory you need to explicitly dismiss them.
The method presentViewController:animated:completion: sets the
presentedViewController property to the specified view controller,
resizes that view controller’s view and then adds the view to the view
hierarchy.
So you see you are getting a stack of ViewControllers and adding a View on top of another.

iOS presented UINavigationController gets dismissed after it performs a popViewController

In my app i present a UINavigationController modally with a UIViewController as its rootViewController. I do it in form style. I added a second UIViewController which is also in form style and i can push to it fine. However when i perform a popViewController action after the second UIViewcontroller gets popped onto the first, the whole modally presented UIViewController gets dismissed. However i don't perform any dismissing and the dismissing function doesn't get triggered by accident either.
Any ideas why it's happening?
Sincerely,
Zoli
EDIT:
That's how i'm presenting the modal viewcontrollers with a navcontroller:
if(!welcomeScreenAlreadyPresented) {
welcomeScreenViewController = [[WAWelcomeViewController alloc]init];
}
welcomeScreenNavController = [[UINavigationController alloc]initWithRootViewController:welcomeScreenViewController];
[welcomeScreenNavController setModalTransitionStyle: UIModalTransitionStyleCrossDissolve];
[welcomeScreenNavController setModalPresentationStyle:UIModalPresentationFormSheet];
[welcomeScreenNavController setNavigationBarHidden:YES animated:NO];
[self.navigationController presentViewController:welcomeScreenNavController animated:YES completion:nil];
That's how i'm navigation in WAWelcomeViewController.m
registerViewController = [[WARegisterViewController alloc]init];
[self.navigationController pushViewController:registerViewController animated:YES];
And in WARegisterViewController.m that's how i pop back
[self.navigationController popViewControllerAnimated:YES];
What you need to do is put the viewController you want to push inside another UINavigationController.
registerViewController = [[WARegisterViewController alloc]init];
UINavigationController *modalNavigationController = [[UINavigationController alloc] initWithRootViewController:registerViewController]; // autorelease if you are not using ARC
[self presentViewController:navController animated:YES completion:^{}];
You might want to add the modalNavigationController as a property to later call popViewControllerAnimated: on it.

Resources