I have two UINavigationController.
The second UINavigationController is segue from the first one.
How do I go back to the initial View.
Below is the storyboard.
note: The root view of the initial NavigationController is has a container from which is am performing segue
#IBAction func dismissView(){
self.dismissViewControllerAnimated(true, completion: nil)
}
Related
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 UINavigationController with several pushed view controllers.
UPD: Last pushed controller modally presents another controller.
Also, I have UINavigationControllerDelegate with some logic at navigationController:willShowViewController:animated:.
UPD: Navigation controller is its own delegate. Delegate is set in viewDidLoad method.
Question rises when I try to close all controllers programically from presented view controller:
// Close all controllers in navigation stack
presentingViewController?.navigationController?.popToRootViewController(animated: true)
// Close presented view controller
dismiss(animated: true, completion: nil)
Method navigationController:willShowViewController:animated: is not called. But it is called when I do the same without presented controller (thanks to #donmag for example project where it works).
Searched SO for answers or similar questions, but found nothing, any thoughts?
In your "presenting" VC, you want to implement a delegate/protocol pattern so your "presented" VC can call back and perform the dismiss and popToRoot...
// protocol for the presented VC to "call back" to the presenting VC
protocol dismissAndPopToRootProtocol {
func dismissAndPopToRoot(_ animated: Bool)
}
// in the presenting VC
#IBAction func presentTapped(_ sender: Any) {
if let vc = storyboard?.instantiateViewController(withIdentifier: "presentMeVC") as? PresentMeViewController {
// Assign the delegate when instantiating and presenting the VC
vc.dapDelegate = self
present(vc, animated: true, completion: nil)
}
}
func dismissAndPopToRoot(_ animated: Bool) -> Void {
// this will dismiss the presented VC and then pop to root on the NavVC stack
dismiss(animated: animated, completion: {
self.navigationController?.popToRootViewController(animated: animated)
})
}
// in the presented VC
var dapDelegate: dismissAndPopToRootProtocol?
#IBAction func dismissTapped(_ sender: Any) {
// delegate/protocol pattern - pass true or false for dismiss/pop animation
dapDelegate?.dismissAndPopToRoot(false)
}
Here's a full demo project: https://github.com/DonMag/CustomNavController
From documentation:
popToRootViewControllerAnimated:
Pops all the view controllers on the stack except the root view controller and updates the display.
popViewControllerAnimated:
Pops the top view controller from the navigation stack and updates the display.
So seems like in order to get navigationController:willShowViewController:animated: called every time you have to do subsequent popViewControllerAnimated:, because the display got updated each time after you pop a new controller. When you pop to root view controller, update display is called only once.
I want to segue to a new ViewController programatically but when I do my tabBar disappears.
if user == usernameStored && pass == passwordStored{
print("Good")
let vc = self.storyboard?.instantiateViewController(withIdentifier: "home")
self.present(vc!, animated: true, completion: nil)
}
From your code, this is not segue by programmatically. You actually present a viewController on top of whatever you have. Therefore the tabBarController is cover.
To use segue in code, it should be something like this. - homeSegueID is the identifier you give when you created the segue in storyboard.
performSegue(withIdentifier: "homeSegueID", sender: nil)
If you just want to do it programatically without segue, you could do this instead. (This assume your current ViewController is in a UINavigationController stack.
navigationController?.pushViewController(vc, animated: true)
Is the navigation controller wrapping your view controllers a tab bar controller, or did you just add the tab bar to your view controller? This is what you should be doing:
I have two view controllers and a button in my storyboard. I don't understand why this is not pushing the view to the second view controller. I have the Storyboard ID and Class of FirstViewController, so shouldn't it work? I keep getting this error Unknown class FirstViewController in Interface Builder file. What am I doing wrong?
#IBAction func button(sender: AnyObject) {
let viewController = self.storyboard?.instantiateViewControllerWithIdentifier("FirstViewController")
self.navigationController?.pushViewController(viewController!, animated: true)
}
Just to have an answer for others -->
Two ways to solve it ->
1.Add a navigationController in the storyboard, as you cannot do pushViewController on a viewController outside navigationController's stack.
2.You can push it as a modal view controller, using self.presentViewController(viewController, animated: true, completion: nil)
This will give a modal effect, and not the normal push effect.
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.