How can I get UINavigationController.pushViewController to push on a presented viewController - ios

I have initialized UINavigationController - nc with VC0
I am in VC0
In VC0, I want to present a "VC1" bottom-to-top
In VC0, [self.nc presentViewController:VC1]
Now I am in VC1
In VC1, I want to present VC2 right-to-left
In VC1, I tried [self.nc pushViewController:VC2]
But it does not work
How can I accomplish the above?

VC1 needs to be in its own UINavigationController. If you put a breakpoint at the point you try to call pushViewController:animated:, you'll notice that the navigation controller property on VC1 is nil.
When you present VC1 do this instead:
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:vc1];
[self.navigationController presentViewController:navigationController completion:nil];
You can then do your pushViewController:animated: call.

Related

IOS/Objective-C/Storyboard: Prevent ViewController From Launching Modally

I want a viewcontroller to launch using a show transition, not modally from the bottom. Normally when I use the following code that's what happens. However, in this case, it is launching as a modal controller from the bottom up. Is there a switch I don't know about or could something be set in Storyboard that is causing this VC to launch modally from the bottom instead of showing?
UIStoryboard *storyBoard = self.storyboard;
IDImportEventsOnboard *importEvents =
[storyBoard instantiateViewControllerWithIdentifier:#"importEventsOnboard"];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController: importEvents];
[self presentViewController:nav animated:YES completion: nil];
The VC is embedded in a navigation controller.
Should I be using showViewController directly to the targetVC without going through the Nav? Or a pushViewController What is a proper, robust way to show a VC with a show transition?
Thanks in advance for any suggestions.
In the above code you are 'presenting' a new NavigationController from a ViewController. In order to do a push/show transition, that needs to be done on an instance of a NavigationController. If your current ViewController is already in a NavigationController, you can push the new ViewController onto the current NavigationController stack. For Example:
UIStoryboard *storyBoard = self.storyboard;
IDImportEventsOnboard *importEventsVC =
[storyBoard instantiateViewControllerWithIdentifier:#"importEventsOnboard"];
[self.navigationController pushViewController:importEventsVC animated:YES];

Push view from modal view and then popToRootView

Here are my ViewControllers as fallows(objects):
FirstViewController - view with tab bar + navigation bar, also part of the ta bar;
SecondViewController - view only with navigation controller
ThirdViewController - view only with navigation controller
And what I am trying to do(logical steps):
present SecondViewController from FirstViewController (modal)
push ThirdViewController from SecondViewController (push)
popToRootViewControllerAnimated - to pop from ThirdViewController to FirstViewController (pop)
And here is the code that I am using by steps:
in FirstViewController class
SecondViewController * secondViewController = [[UIStoryboard MainStoryboard] instantiateViewControllerWithIdentifier:NSStringFromClass([SecondViewController class])];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController: secondViewController];
[self.navigationController presentViewController: navigationController animated:YES completion:nil];
in SecondViewController class:
ThirdViewController * thirdViewController = [[UIStoryboard MainStoryboard] instantiateViewControllerWithIdentifier:NSStringFromClass([ThirdViewController class])];
[self.navigationController pushViewController: thirdViewController animated:YES];
and in ThirdViewController class I do:
[self.navigationController popToRootViewControllerAnimated:YES];
My issues is on point 3, when I do the pop to root view controller instead of going from ThirdViewController to FirstViewController it only goes to SecondViewController.
In step 1 you created new UINavigationController instance and you set secondViewController as the rootViewController for it. So now in step 2 when you are pushing the thirdViewController it will get added to the navigation stack of secondViewController.
Finally in step 3 when you are calling "popToRootViewControllerAnimated" it will pop to secondViewController, since secondViewController is the rootViewController of the navigation.
To go to FirstViewController call "dismissViewControllerAnimated" on self.navigationController.
Please refer the below code.
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
Forget about the frist step. Even though you are presenting a view controller modally, you are making it a root view controller till you dismiss it.
You are pushing it from second VC nav controller.
If you pop it, you will go back to second VC, as the third VC is pushed on second nav controller.
If you want to go to your first View controller,present the first VC again in the third VC by
[self presentViewController:firstVC animated:YES completion:nil];
or you can dismiss
[self.navigationController dismissViewController animated:YES completion:nil];
Please note that you cannot have multiple navigation controllers in the reference. You can have only one at any time.
Even though you present the second VC by from first VC nav controller
[self.navigationController presentViewController:secondVC animated:YES completion:nil];
you are presenting the second VC navigation controller here, so in the first VC navigation stack another nav controller will be added. At this point, the second VC navigation controller will be in reference when you call self.navigationController in the secondVC

Push to a UIViewController from a presentViewController

I want to push to a new viewcontroller from a presented viewcontroller. I don't want to dismiss the presented viewcontroller. I want the new viewcontroller to come over the presented viewcontroller.
Can anybody tell me how to do that.
You do not push form the presented controller so the best option is
First you have to dismiss the controller without animation and then in the method of -(void)viewWillApper you can easly push to the controller where you want to push.
You can do by using UINavigationController like
UINavigationController *vcObject = [[UIStoryboard storyboardWithName:#"Main" bundle:nil] instantiateViewControllerWithIdentifier:#"YourViewController"];
[self.navigationController presentViewController:vcObject animated:YES completion:NULL];
Now you can easily push or pop to other ViewController like you want.Thankyou
Open your modalView controller as a new rootViewController :
UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:nextViewController];
[self.navigationController presentViewController: navController animated:YES completion:nil]

Calling pushViewController after a presentViewController does not work

I am presenting my view controller like this -
[self.navigationController presentViewController:self.thingContainerViewController animated:YES completion:nil]; //self.navigationController not nil here
This shows a UITableView. I want to push a VC on the navigation stack from here. But the self.navigationController is nil at this point. Any idea how to make this work?
[self.navigationController pushViewController:otherContainer animated:YES]; //self.navigationController is nil at this point
You need to wrap the view controller you are presenting in a navigation controller in order to be able to use the push and pop methods.
So for the first step:
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:self.thingContainerViewController];
Then:
[self.navigationController presentViewController:navigationController animated:YES completion:nil];
If you do that, your code will work.
Swift 3/Swift 4
first of all you need to set navigation controller on which you want to present.After that do navigation process on your second view controller.
Example like that
let firstPresentVC = FirstVC(nibName:"FirstVC",bundle:nil)
let navVC = UINavigationController(rootViewController:firstPresentVC)
navVC.isNavigationBarHidden = true
self.present(navVC, animated: true, completion:nil)
Now You are on Present Stack With Navigation
You can push after that
let secondPushVC = secondPushVC(nibName:"secondPushVC",bundle:nil)
self.navigationController?.pushViewController(secondPushVC, animated: true)
UIViewController.navigationController means:
The nearest ancestor in the view controller hierarchy that is a navigation controller.
on the other hand, presentViewController makes new view controller out of hierarchy, the new view controller has no navigation controller ancestor unless you assign one to it by [[UINavigationController alloc] initWithRootViewController:self.thingContainerViewController] as #Dima mensioned.
so, the solution is
UINavigationController *targetVCWithNavigationControllerAncestor = [[UINavigationController alloc] initWithRootViewController:self.thingContainerViewController];
[self.navigationController presentViewController:targetVCWithNavigationControllerAncestor animated:YES completion:nil];
then you can push new view controller from self.thingContainerViewController

What exactly does presentModalViewController do?

If I have a navigationController which is init with a root view controller MyViewController's instance.
And in that MyViewController's code
I can use
AnotherViewController *vc = [[AnotherViewController alloc] init];
[self presentModalViewController:vc animated:YES];
or
AnotherViewController *vc = [[AnotherViewController alloc] init];
[self.navigationController presentModalViewController:vc animated:YES];
I found these two works the same. Both present the modal view correctly.And I have found that the presented AnotherViewController's "parentViewController" property are all set to the navigation controller.
Why would this happen?the presentModalViewController automatically detect that the self is the subview of the navigation controller and re send the message to navigation controller?
Because MyViewController is the root view controller of the UINavigationController, it gets the convenience method of presentModalViewController: animated: by default. So when you say self.navigationController, it is referring to the same navigationController that presentModalViewController gives you. I think Apple is just trying to make it more intuitive to use the convenience method.

Resources