How can I dismiss a UINavigationController presented modally? - ios

I have the following structure:
UINavigationController(1) -> MainViewController ---PRESENT MODAL--->
UINavigationController(2) -> TutorialViewController ---PRESENT MODAL---> LoginViewController
---PRESENT MODAL---> SignupViewController
I want to dismiss the UINavigationController(2) from a user action on LoginViewController.
Any idea?

You should use delegation to dismiss the second view controller. So you would have the second nav controller be dismissed by the first nav controller, the one that presented it. This is the recommended way to dismiss modal views.
Here are the docs on delegation

Related

How does dismissing a presented UIViewController work?

Apple's View Controller Programming Guide for iOS states:
To dismiss a presented view controller, call the dismissViewControllerAnimated:completion: method of the presenting view controller. You can also call this method on the presented view controller itself. When you call the method on the presented view controller, UIKit automatically forwards the request to the presenting view controller.
This is verified by the UIViewController documentation:
The presenting view controller is responsible for dismissing the view controller it presented. If you call this method on the presented view controller itself, UIKit asks the presenting view controller to handle the dismissal.
However this behavior seems ambiguous to me. What if a UIViewController is both presented and presenting? If you call dismiss(animated:completion:) on it, will it pass the call to its presentingViewController which will dismiss it, or will it dismiss its presentedViewController?
For example, suppose I have a UIViewController vc1, which creates and presents a UIViewController vc2, which then creates and presents vc3. So vc1 has vc2 as its presentedViewController, vc2 has vc1 as its presentingViewController and vc3 as its presentedViewController, and vc3 has vc2 as its presentedViewController. Then dismiss(animated:completion:) is called on vc2. Which is dismissed, vc2 or vc3? If vc2 is dismissed, what happens to vc3?

poptorootviewcontroller and dismiss to mainViewController

i am new to IOS .
My question is, i have some view-controllers as NavigationController,mainVC, VC1, VC2, VC3, CameraVC. In cameraVC i have a done button having action doneClicked. These all View-Controller are pushed in NavigationController. VC1 is presented, not pushed in nav-controller. doneClicked function implemented poptorootviewcontroller. when i click on done button it let me to VC1 but not the mainVC. Is there any way so i can pop all view controller to VC1 and after this automatically dismiss VC1 to mainVC.
Make your MainVC as root view controller and in the IBAction of done button use the code to pop to MainVC.
[self.navigationController popToRootViewControllerAnimated:YES];
Hope it helps.
To pop view controllers
[self.navigationController popToRootViewControllerAnimated:YES];
and to dismiss presented view controller
[self dismissViewControllerAnimated:NO completion:nil]
[self.navigationController setViewControllers:#[mainVC]];
I think this code will work on your situation. iOS Developer Library:
Replaces the view controllers currently managed by the navigation controller with the specified items.
- (void)setViewControllers:(NSArray *)viewControllers
animated:(BOOL)animated
source
you must do this after dissmiss present view controller. Use delegate
Now let's think your navigation stack is empty and your root is mainVC. you want to present VC1 that's ok just present it. But you should give a delegate to mainVC to what's gonna happen after dissmissing VC1. For example you present VC1 from mainVC. And you want to push VC2 after dissmiss VC1. That's ok just in mainVC has a delegate so in this method
[self.navigationController pushViewController:VC2];
Present views does not affect your navigation stack. It's not in your stack. so everytime you dismiss it from a controller you should give an delegate to that controller to what will happen after dissmissing.
Try it.
Hope it helps.

How to dismiss a viewController pushed from a modalViewController without dismissing the modal?

This is the design of the app:
TabBarController -> NavigationController -> Show ModalViewController -> Push another ViewController on top (by segue)
How can I dismiss the last ViewController without dismissing the ModalViewController?
if your design is like this
TabBarController -> NavigationController -> rootviewcontroller -->Show ModalViewController -> Push another ViewController2 on top (by push segue)
firstly you cannot push viewcontroller on top of modalviewcontroller , if you try that .
viewcontroller will be pushed on back of modalviewcontroller and when you dismiss that modal viewcontroller you will see viewcontroller2 is shown.
I was able to dismiss the viewController by simply [self.navigationController popViewControllerAnimated: YES]. The dismiss was dismissing all the modal view controller.

dismissViewControllerAnimated:Completion: Concept?

I have 3 viewControllers - BaseViewController->AviewController->BviewController.
AviewController is presented modally on BaseViewController and BviewController is presented modally on AviewController.
In AviewController if I call [self dismissViewControllerAnimated:Completion] it dismisses both AviewController and BviewController.
In BviewController if I call [self.presentingViewController dismissViewControllerAnimated:completion] it only dismisses BviewController.
Why is AviewController not dismissed ?
Is this concept wrong AviewController = BviewController.presentingViewController. ?
I also tried taking weak reference of AviewController in BviewContrroller and tried to dismiss. But still only BviewController alone is dismissed.
i.e [AviewControllerReference dismissViewControllerAnimated:completion]
Any mistake in my understanding of the concept?
From apple docs:
The presenting view controller is responsible for dismissing the view
controller it presented. If you call this method on the presented view
controller itself, it automatically forwards the message to the
presenting view controller.
So you must call this method on presenting VC to dismiss the presented controller. Not presented controller it self. As you can see in above in bold test, if you called this on a presented VC it automatically forwards the method to prsenting VC.
So to answer to your issue,
Call below line on BViewController to dismiss both AViewcontroller and BViewController. ,
[self.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
this is Equalent to calling dismissViewController: on your BaseViewController. Which is the correct way of dismissing AViewController

Programmatically dismiss popover from view embedded in navigation controller

I have a view controller. When I press a button in it, a popover controller with a uitableview shows up. I select a row, which shows another view with some controls in it. When I press a button that says "Save Item", I want it to dismiss the popover. How do I do this?
Here's what I've tried:
Using the delegate and protocol pattern. This hasn't worked since in order to push another view inside my tableview, the whole thing must be embedded in a navigation view controller, so when I segue, it segues to a nav controller, not the tableview which I could set the popover delegate for.
Adding my main view as a member of the view I want to dismiss from. I don't know why this doesn't work.
The Hard Clean Way
There are four view controllers in the story, plus a popover controller. I will call the three view controllers "main view controller", "nav", "vcA", and "vcB". As I understand it, "nav" is the initial content view controller of the popover and has "vcA" as its root view controller.
main view controller -> popover controller -> nav -> vcA -> (later) vcB
When you present the popover from your main view controller, you keep a reference to the popover controller. This is what makes dismissing possible, as you know.
When you create the Save button, you make its target the main view controller and its action a method in the main view controller. You will have to set this up in code; it cannot be configured from a storyboard because you cannot form an action from one scene to another. (You are able to do this because you started out with a reference to nav and vcA when you configured the popover controller initially. Thus you can hand vcA a reference to self, the main view controller. If necessary, you can then pass this reference down the chain from vcA to vcB as vcB is summoned and pushed onto the navigation stack.)
Now the user taps Save, your main view controller's method runs, and it uses its reference to the popover controller to tell it to dismiss.
The Easy Dirty Way
The heck with all that. The main view controller registers for an NSNotification. The Save button posts that NSNotification. Done. :)
The Middle Way
You could set the whole chain up in your storyboard using a popover segue, and do the dismissal through an Unwind segue matched by an unwind method back in the main view controller. I never think of this initially, because I don't like popover segues very much. But it does work.
This is how I solved my problem (sorry for the bad english):
First, Create a property of UIStoryboardPopoverSegue in the VcA and set it from the main view controller.
Nav -> VcA_ViewController
#property (strong, nonatomic) UIStoryboardPopoverSegue *popupSegue;
Then, in the Main View Controller prepareForSegue set the property:
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:#"your segue from the mainview to the navigation"]) {
UINavigationController *navigationController = (UINavigationController *)c;
VcA_ViewController *vcA = (VRPointOfInterestsFiltersViewController *) navigationController.topViewController;
vcA.popupSegue = (UIStoryboardPopoverSegue*)segue;
} }
Now, from the VcA controller you can have the dismiss button
- (IBAction)dismissPopoup:(id)sender {
[self.popupSegue.popoverController dismissPopoverAnimated:YES]; }
Don't forget to link the popOverSegue from the MainViewController to the NavController.
Hope it helps!

Resources