Dismiss 2 UIViewController that was loaded via a presentViewController - ios

When the user clicks on a button I am displaying a UIViewController as follows:
NSString * storyboardName = #"Main";
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:storyboardName bundle: nil];
UIViewController * vc = [storyboard instantiateViewControllerWithIdentifier:#"newviews"];
[self presentViewController:vc animated:YES completion:nil];
However, when the vc viewcontroller loads successfully, the user will click on another button and another UIViewcontroller is displayed. Again this too uses a presentViewController: as in the previous code.
Now, there's 2 UIViewController that's being displayed by presentViewController:,
When the user clicks on a button I need these 2 ViewControllers to Dismiss. How can I do this ?
I tried the following code but it did not work.
[self.navigationController popToRootViewControllerAnimated:YES];

You need to use [self.parentViewController dismissViewControllerAnimated:YES] since you presented them modally. You can take advantage of the parentViewController property when dismissing viewControllers.
UIViewController *mainController = [UIViewController new];
UIViewController *vcA = [UIViewController new];
UIViewController *vcB = [UIViewController new];
// User taps button to present vcA
[mainController presentViewController:vcA animated:YES completion:nil];
// User taps button to present vcB
[vcA presentViewController:vcB animated:YES completion:nil];
// Dismiss both vcB and vcA
[vcB.parentViewController dismissViewControllerAnimated:YES completion:^{
[vcA.parentViewController dismissViewControllerAnimated:YES completion:^{
// Now you are back on mainController
}];
}];

Related

Present a ViewController that is embedded in Navigation Controller

I have a situation wherein a storyboard made VC(embedded in NavController) should be presented programmatically.
SomeVC -> presents NavController(rootVC) -> rootVC -> pushes subVC
on this representation, subVC should have a back button to go back to rootVC, but I can't implement it this way. Will be providing sample codes that I have already tried.
this pushes the rootVC directly:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"storyBoard" bundle: nil];
UIViewController * vc = [storyboard instantiateViewControllerWithIdentifier:#"rootVC"];
[self.navigationController presentViewController:vc animated:YES completion:nil];
also tried pushing the navigationController itself, ID has been set on storyboard:
UINavigationController *navController = [storyboard instantiateViewControllerWithIdentifier:#"navigationController"];
[self presentViewController:navController animated:YES completion:nil];
EDIT: storyboard implementation looks like this
I'm not sure if I understand you correctly. You want to present a navigation controller and have those rootVC and subVC already in it, right? So after presenting, you want the subVC to be presented with the back button right away.
If that's the case you need to tell the navigation controller to push the subVC before presenting it
UINavigationController *navController = [storyboard instantiateViewControllerWithIdentifier:#"navigationController"];
UIViewController *subVC = [storyboard instantiateViewControllerWithIdentifier:#"subVC"];
[navController pushViewController:subVC animated:NO];
[self.navigationController presentViewController:vc animated:YES completion:nil];

PresentViewController dismiss doesn`t go back to previous viewController

On my project we have three windows A, B and C. From A I would like to push view B, and from B I would like to present view C.
My code:
ViewController A:
ViewControllerB *vcB = [[viewControllerB alloc]
initWithNibName:#"ViewControllerB" bundle:nil];
[[self navigationController] pushViewController:vcB animated:YES];
View Controller B:
ViewControllerC *vcC = [[ViewControllerC alloc]
initWithNibName:#"ViewControllerC" bundle:nil];
[self presentViewController:vcC animated: true completion: nil];
Everything is ok until now, but when I dismiss the last view controller with:
[[self presentingViewController] dismissViewControllerAnimated:NO completion:nil];
The app goes back to first view controller (vcA) instead the second one (vcB)
What am I doing wrong?
Thank you, guys.
You must be doing something else that you're not telling us about...
This works as expected:
In MyFirstViewController.m
- (IBAction)pushTapped:(id)sender {
MyPushedViewController *vc = [[MyPushedViewController alloc] initWithNibName:#"MyPushedViewController" bundle:nil];
[self.navigationController pushViewController:vc animated:YES];
}
In MyPushedViewController.m
- (IBAction)presentTapped:(id)sender {
MyPresentedViewController *vc = [[MyPresentedViewController alloc] initWithNibName:#"MyPresentedViewController" bundle:nil];
[self presentViewController:vc animated:YES completion:nil];
}
In MyPresentedViewController.m
- (IBAction)dismissTapped:(id)sender {
[self dismissViewControllerAnimated:NO completion:nil];
}
Tapping the "dismiss" button in MyPresentedViewController dismisses the presented view controller (your vcC), leaving me at MyPushedViewController (your vcB) ... NOT at MyFirstViewController (your vcA).
try this to dismiss vc
[self dismissViewControllerAnimated:NO completion:nil]
and use this to pop
[self.navigationController popToViewController:controller animated:YES];
[self presentingViewController] = Bvc , so here you actually dismissing B not C
[Bvc dismissViewControllerAnimated:NO completion:nil];
but self = Cvc so here you dismissing C only
[self dismissViewControllerAnimated:NO completion:nil];

Showing view controller from AppDelegate when notification arrived

I am tring to show UIViewController which is inside the UIStoryboard. There isn't any problem about poping up the view. But the navigation is not working in the popup viewcontroller; such as when I touch back button
[self.navigationController popViewControllerAnimated:YES];
I am using that code in AppDelegate --> didReceiveRemoteNotification method
UIStoryboard *mystoryboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
PFProfileInfoVC *viewcontroller = [mystoryboard instantiateViewControllerWithIdentifier:#"SBID_ProfileVC"];
viewcontroller.strAuthorID = [userInfo objectForKey:#"aps"][#"targetId"];
[self.window.rootViewController presentViewController:viewcontroller animated:YES completion:nil];
Thanks,
When you use presentViewController, the viewController is not pushed onto the navigation stack. Normally, it is presented modally. So if you want to dismiss it, use
[self dismissViewControllerAnimated:true completion:nil];

Need to return to the presenting UIViewController from within a presented UINavigationController

In MyMainViewController, I present a navigation controller like this:
UIStoryboard* storyboard = [UIStoryboard storyboardWithName:#"Main_iPhone" bundle:nil];
UINavigationController* nc = [storyboard instantiateViewControllerWithIdentifier:#"NAVIGATION_CONTROLLER_ID"];
[self presentViewController:nc animated:YES completion:nil];
Later, from somewhere within the view hierarchy of the UINavigationController, I need to return to MyMainViewController. How can I do this?
(Note: MyMainViewController is defined in a .XIB, and not in the storyboard where the UINavigationController and it's children are defined.)
It sounds like you have modally presented a NavController that you want to remove. Modally presented VC's can remove themselves.
Somewhere in your NavController add:
[self dismissViewControllerAnimated:YES completion:^{
NSLog(#"Dismissed nav controller modally");
}]
[self.navigationController popToViewController:[[self.navigationController viewControllers] objectAtIndex:2] animated:YES];
I gues you know the index of your view controller. If you simply want to return to the rootViewController you can do it like
[self.navigationController popToRootViewControllerAnimated:YES];
If you want to push new viewController to the navigation stack just do it like
MyMainViewController *mainController = [[MyMainViewController alloc] initWithNibName:#"MyMainViewController" bundle:nil];
[self.navigationController pushViewController:desController animated:YES];
Returning to the previous viewController would be
[self dismissViewControllerAnimated:YES completion:nil];

Removing ViewController after showing modally a second ViewController

Guys in my app I have some code in the app delegate method application:didFinishLaunchingWithOptions: that determines if the initial View Controller should be the LoginViewController or the MainViewController.
If the LoginViewController is showed first and the user logs in successfully I show the MainViewController modally with this piece of code:
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
FSMainViewController *vc = (MainViewController *)[storyBoard instantiateViewControllerWithIdentifier:#"MainViewController"];
vc.loginViewController = self;
[self presentViewController:vc animated:YES completion:nil];
What I want to do next, after the MainController is showed on the screen, is remove the LoginViewController from memory so in the viewWillApper:animated: method of the MainViewController I use this code to remove (or at least try to) the LoginViewController:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
if (self.loginViewController) {
[self.loginViewController dismissViewControllerAnimated:NO completion:nil];
}
}
Problem is that this code leads to strange behaviors like the MainViewController being removed from the screen and this error message showing up in the console.
Unbalanced calls to begin/end appearance transitions for <LoginViewController: 0xb06e350>
I also tried calling [self dismissViewControllerAnimated:NO completion:nil] in the completion block of the presentViewController:animated:completion method but still no luck, it didn't work.
What am I doing wrong? How can I remove from memory the underlying LoginViewController when the MainViewController is presented modally?
Don't present your main view controller if you want the login controller to go away, just make it the window's root view controller.
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
FSMainViewController *vc = (MainViewController *)[storyBoard instantiateViewControllerWithIdentifier:#"MainViewController"];
Self.window.rootViewController = VC;
You can't dismissViewController after presenting another one on it or its presentingViewController. At here, you should dismiss LoginViewController first, then present MainViewController.
Otherwise, if you'd like pushViewController, you can call [self.navigationController setViewControllers: animated:] to remove LoginViewController.
If you think presentingViewController is just what you want, try something like this in application:didFinishLaunchingWithOptions:
if (self.loginViewController) { //Define loginViewController in appDelegate.h
[self dismissViewControllerAnimated:NO completion:^{
[self presentViewController:mainViewController animated:YES completion:nil];
}];
}
else{
[self presentViewController:mainViewController animated:YES completion:nil];
}

Resources