I'm opening a navigation controller from a button click of my main view controller.
I programatically created a left bar button item on the navigation controller which I want to dismiss the nav controller and go back to my main controller.
I'm essentially going back on the root view controller of the navigation controller.
I've tried
navigationController?.dismissViewControllerAnimated(true, completion: nil)
and
self.dismissViewControllerAnimated(true, completion: nil)
and get an NSException on both.
Please advise.
Swift 3:
self.view.window!.rootViewController?.dismiss(animated: false, completion: nil)
It will dismiss all the presented view controllers and remain root view controller.
If you are pushing your ViewController, you should use pop to remove that ViewController from Navigation Stack and land on the previous ViewController. Try this...
self.navigationController?.popViewControllerAnimated(true);
SWIFT 3
_ = navigationController?.popViewController(animated: true);
dismissViewController works when you are showing a viewController using presentViewController, that maybe the root view controller of a navigation stack, or a stand alone view controller.
self.presentingViewController?.presentingViewController?.dismissViewControllerAnimated(true, completion: nil)
Try this :)
A year later.. The exception indicates that there is something wrong with the selector that you provide to the action param, when adding the left bar button.
Something like this should work:
creating bar button item:
let backBarButton = UIBarButtonItem.init(barButtonSystemItem: UIBarButtonSystemItem.stop, target: self, action: #selector(dismissView))
dismiss root view controller:
func dismissView() {
self.dismiss(animated: true, completion: nil)
}
Apple Dev already provides very simple code which is
self.navigationController?.popToRootViewController(animated: false)
Related
I am trying to pop a view controller VC1 from one navigation controller NC1 to another view controller VC2 in another navigation controller NC2.
I am using the VIPER architecture thus routing between different view controllers in different navigational hierarchies requires that I must switch to the root of the navigation controller I want to present.
So the issue here is that, after navigating to the view controller VC2 of the second navigation controller NC2, I want to go back to the first view controller VC1 in the first navigation controller NC1.
I have tried the following:
self.navigationController?.popViewController(animated: true)
navigationController?.dismiss(animated: true, completion: nil)
view.window?.rootViewController?.dismiss(animated: true, completion: nil)
self.navigationController?.popToRootViewController(animated: true)
but none of them worked for me. Any ideas?
Please Try this codes :
let viewControllers = self.navigationController?.viewControllers
for vc in viewControllers! {
if vc is VC1 {
self.navigationController?.popToViewController(vc as! VC1, animated: true)
}
}
I'm totally newbie level with swift and having a question. so, I created a navigation controller for my modal and having my modal opened up from my first view controller with segue (Button2). The question is, how to get back to my first view controller from Modal View
You can use the dismiss method to dismiss a specific ViewController.
The question is how you want to dismiss the ViewController presented modally? With a button? Tap anywhere in the View? Tap on a little cross button?
For example if you have an UIButton to dismiss:
#IBAction func didTapClose(_ sender: UIButton) {
dismiss(animated: true, completion: nil)
}
If the segue is "present modally", you can dismiss the view controller through this line :
dismiss(animated: true, completion: nil);
Else If the segue is "show", you can dismiss the view controller through this line :
navigationController?.popViewController(animated: true);
In this case, be sure that you embedded your ViewController to a navigationController in your storyboard. If your ViewController is not embedded to a navigationController and you have used show segue, you should use dismiss(animated: true, completion: nil) to return to previous page.
Also there is other ways to return to previous pages (e.g., unwind segue)
Good luck.
I have created a simple tab bar with three views in storyboard. The tab bar works well, but when I try to show another view controller from a button within a tab, the new view is placed over the whole screen and also over the tab bar.
This is how I present the view so far when a button is pressed:
#IBAction func buttonPressed(_ sender: UIButton) {
let newVC = self.storyboard?.instantiateViewController(withIdentifier: "extraVC")
self.present(newVC!, animated: true, completion: nil)
}
The other idea I had was this:
self.tabBarController?.present(vc!, animated: true, completion: nil)
But this didn't work either.
So how can I present another view controller within the tab bar (so that the bottom bar is still shown)?
When you present a view controller modally, its presentation style will be "Full Screen" by default. What you want to do is have it do in this case is just cover part of the screen (the part where the presenting view controller is drawn.
One way to accomplish this is to:
Set the modalPresentationStyle for the presented view controller to be .currentContext or .overCurrentContext
In the view controller that will be presenting the modal, set its definesContext property to true.
These steps can be done either in Interface Builder by setting attributes on the segue and the view controller, or you can modify your code to include the following:
#IBAction func buttonPressed(_ sender: UIButton) {
let newVC = self.storyboard?.instantiateViewController(withIdentifier: "extraVC")
self.definesPresentationContext = true
newVC?.modalPresentationStyle = .overCurrentContext
self.present(newVC!, animated: true, completion: nil)
}
What this combination of properties does is:
Indicate for the presented view controller that you want it to be presented in a non-full screen context (some specific section of the screen)
Indicate that the presenting view controller is in the section of the screen / the context you want the modal to be drawn according to.
More details can be found in the Apple Documentation
When you are using present method, the ViewController is presented modally and covers your UITabBarConntroller. Instead of showing your view modally you can embed every first view controller in your TabBar into UINavigationController and then use method pushViewController to push it onto stack. You will have your TabBar visible and nice looking animation for free.
In Xcode, I created a new project using the Tabbed App template to illustrate the solution above. This will create a project with a tabbar controller and two view controllers. I added a button with the title "view page" to the first view controller and embedded a navigation controller from the storyboard.
The storyboard will look like this after making the above changes:
In the FirstViewController.swift file, I created an IBAction for the button with the following code that will create another view controller called DetailViewController, with the title Favorites and a background color of orange. I used the navigation controller to present it by pushing it onto the navigation controller stack.
#IBAction func viewPageButtonTapped(_ sender: UIButton) {
print("viewPageButtonTapped")
let pinkViewController = DetailViewController()
pinkViewController.title = "Favorites"
pinkViewController.view.backgroundColor = UIColor.orange
navigationController?.pushViewController(pinkViewController, animated: true)
}
When I run the project on the simulator, I got the desired result. Hope this helps give you some ideas.
In your viewController do:
self.tabBarController?.present(nextViewController, animated: true/false, completion: {})
My first view controller has a button, which triggers the #IBAction goTo2ndVc() which presents a second ViewController:
class FirstVC: UIViewController {
...
#IBAction func goTo2ndVc() {
let secondVc = SecondVC(label: "I am second vc.")
self.presentViewController(secondVc, animated: true, completion: nil)
}
When the button is pressed, the 2nd view controller is shown on screen. No problem.
In 2nd view controller, there is also a button which is used to go back to 1st view controller:
class SecondVC: UIViewController {
...
#IBAction func backToFirst(sender: AnyObject) {
print("go back ...")
self.navigationController?.popViewControllerAnimated(true)
}
}
I looked on internet, people suggest to use navigationController?.popViewControllerAnimated(true) to go back to previous controller. But when I press the go back button I can see the print message "go back ..." but the app doesn't go back to 1st view controller. WHY?
#IBAction func backToFirst(sender: AnyObject) {
print("go back ...")
self.dismissViewControllerAnimated(true, completion: nil)
}
In Swift 3
self.dismiss(animated: true, completion: nil)
you should not use navigation controller, because you didn't use it when you were adding the second view controller. that's why simply call dismissViewControllerAnimated method.
You have to use UINavigationController and its pop methods only when you add your view controllers via pushViewController method.
Familiarize yourself with the concept of navigation controller here: https://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/ViewControllerCatalog/Chapters/NavigationControllers.html
there
the issue is very simple..
self.presentViewController(secondVc, animated: true, completion: nil)
the code will present second view, you are not pushing it.
self.navigationController?.popViewControllerAnimated(true)
the popViewController will pop back to the previous view controller from where it is been pushed.
So, there are two ways you can achieve what you want
1)If you want to present viewController then you have to dismiss the view controller to show previous view controller with
self.dismissViewControllerAnimated(true, completion: nil)
2)If you want to use PopToVewcontroller, then you have to push you second view controller instead of presenting it with
self.navigatioVonroller?.pushViewController(secondVc, animated: true)
If you want to return to the previous view controller, you can simply add:
[self dismissViewControllerAnimated:YES completion:nil];
to the button action method.
If this is added on the nav view controller present on every screen, I see no reason why it shouldn't work as it would always dismiss the most recently presented view.
I am working on a project that is a tabbed application. I have a button on my home page that goes to the second tabbed page but when it loads it gets rid of the tabs at the bottom.
How do I prevent this from happening? my code:
func manageButtonPressed() {
let NVC:SecondViewController = SecondViewController()
self.presentViewController(NVC, animated: true, completion: nil)
}
Replace:
self.presentViewController(NVC, animated: true, completion: nil)
With:
self.tabBarController?.selectedIndex = 1
This is assuming that your home page button is at index 0 on the first tab button of Tab bar, while second VC is on second tab at index 1. You may change the index based on the position of your tab bar.
You want to use showViewController method off of a uinavigationcontroller.
So in the main storyboard of the view where you call the presentViewController you need to add a UINavigationController. Then you can call in the view
self.navigationController.showViewController(NVC, sender: self)
Then it will add the view onto the top of the navigation stack and will be underneath the tab bar