I need to switch page(other view controller) using a button.
I have two controllers (viewController to HomeViewController)
I have a button created in viewController:
let acceptButton: UIButton = {
let button = UIButton(type: .system)
button.setTitle("Accept", for: .normal)
button.setTitleColor(.blue, for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 18)
button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
//button.sendAction(Selector(buttonAction), to: HomeViewController(), for: .touchUpInside)
return button
}()
and I have set a function and used a print statement to test the function:
#objc func buttonAction(sender: UIButton){
print("button pressed")
}
I executed the program and when I press the button it prints out "button pressed"
Then I added the following into the function:
let HomeViewController = ViewController(nibName: ViewController, bundle: nil)
self.presentViewController(HomeViewController, animated: true, completion: nil)
As a result, it does not switch to other viewController(HomeViewController).
Any idea on how should I make it works? Thank you
There are couple of ways to switch to another ViewController.
Navigation
Present
If you have created the controllers in storyboard then you have to first get the instance of storyboard in case of multiple storyboards.
In case of multiple storyboard you need to mention the name of the storyboard.
let sampleStoryBoard : UIStoryboard = UIStoryboard(name: "UserBoard", bundle:nil)
Then get the instance of the view controller you wish to switch.
* Make sure you set the correct Identifier in ViewController.
let homeView = sampleStoryBoard.instantiateViewController(withIdentifier: "HomeViewController") as! HomeViewController
if you wish to present the view controller:
self.present(homeView, animated: true, completion: nil)
if you wish to push the view controller:
self.navigationController?.pushViewController(homeView, animated: true)
if you want to Switch to another Controller which you created as Xib
let homeView = HomeViewController(nibName: "HomeViewController", bundle: nil)
If you want to push:
self.navigationController?.pushViewController(homeView, animated: true)
Present the Controller:
present(homeView, animated: true, completion: nil)
Other ways to Switch between Controllers.
Wiring up the Segues
Ctrl+Drag from the “View Controller” button, to somewhere in the second View Controller(HomeViewController). It can be anywhere in the main box of the second view controller. When you release, it will show you a box like the one below.
in this you don't need any code to switch, it will switch on click of a button.
or you can CTLR + Drag from View controller to other controller to create segue and write below code on click of button action and switch to another view controller.
performSegue(withIdentifier: "mySegueID", sender: nil)
make sure you set the correct identifier of segue.
Details of different segues
Show — When the View Controllers are in a UINavigationController, this pushes the next View Controller onto the navigation stack. This allows the user to click the back button to return to the previous screen through the back button on the top left of the Navigation Bar.
Present modally — This presents the next view controller in a modal fashion over the current View Controller. This one doesn’t need to be part of a UINavigationController or a UISplitViewController. It just shows the destination View Controller in front of the previous one. This is usually used when the user has to either Finish or Cancel .
Custom — Exactly what it sounds like. You can make your own segue style and transitions and use it here.
Switch to another viewController programmatically in Swift 4 -
Navigation process
first, you need to embed your view with Navigation Controller like -
For Navigation programmatically you can use below code -
But this code work with if you working with StoryBoard in your project.
First, you need to set view identifier in storyBoard
Push with StoryBoard
let homeView = self.storyboard?.instantiateViewController(withIdentifier: "HomeViewController") as! HomeViewController
self.navigationController?.pushViewController(homeView, animated: true)
Present with StoryBoard
let homeView = self.storyboard?.instantiateViewController(withIdentifier: "HomeViewController") as! HomeViewController
present(homeView, animated: true, completion: nil)
Push with XIB
let homeView = HomeViewController(nibName: "HomeViewController", bundle: nil)
self.navigationController?.pushViewController(homeView, animated: true)
Present with XIB
let homeView = HomeViewController(nibName: "HomeViewController", bundle: nil)
present(homeView, animated: true, completion: nil)
For avoiding any crashes you can also try this code -
guard let homeView = HomeViewController(nibName: "HomeViewController", bundle: nil) else {
print("Controller not available")
return
}
self.navigationController?.pushViewController(homeView, animated: true)
you can switch to a Controller in two ways
Present and Dismiss
Navigation Controller
-> First Method is simple
just need to write two lines as :
In case Controller in Another storyboard file
let newStoryBoard : UIStoryboard = UIStoryboard(name: "UserBoard", bundle:nil)
let VC = newStoryBoard.instantiateViewController(withIdentifier: "HomeViewController") as! HomeViewController
self.present(VC, animated: true, completion: nil)
Or if in same storyboard
let VC = self.storyboard?.instantiateViewController(withIdentifier: "HomeViewController") as! HomeViewController
self.present(VC, animated: true, completion: nil)
-> Second using navigation Controller
Just make use of a navigation controller and then push or pop controllers in navigation stack
let VC = self.storyboard?.instantiateViewController(withIdentifier: "HomeViewController") as! HomeViewController
self.navigationController?.pushViewController(VC, animated: true)
In your case You are providing bundle as Nil which is wrong
let HomeViewController = ViewController(nibName: ViewController, bundle: nil)
///Need to Provide Bundle detail
let HomeViewController = ViewController(nibName: ViewController, bundle: Bundle.main)
let HomeViewController = ViewController(nibName: "ViewController", bundle: Bundle.main)
self.presentViewController(HomeViewController, animated: true, completion: nil)
Related
How can I show() or persent() VC on button touch? What code should I write?
First, using Storyboards
If you are working with storyboard. You should connect your button view storyboard.
#IBAction fileprivate func handlePresentingView(_ sender: UIButton) {
let vc = SecondVC()
present(vc, animated: true, completion: nil)
}
Second, programmatically
1: If you are working programmatically
in viewDidLoad add the following line.
mybutton.addTarget(self, action: #selector(handlePresentingVC(_:)), for: .touchUpInside)
2: Your action method
#objc func handlePresentingVC(_ sender: UIButton) {
let vc = SecondVC()
present(vc, animated: true, completion: nil)
}
In my example, I'm assuming that you don't have a storyboard file for
your SecondVC view controller.
If SecondVC is connected to a storyboard view controller, you will
need to change the instantiation of your secondVC object inside of
your button's action method.
1: Select your SecondVC's view controller in your storyboard.
2: Add a Storyboard ID to it.
3: Change your button's action method to the following.
#objc func handlePresentingVC(_ sender: UIButton) {
let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
let secondVc = storyboard.instantiateViewController(withIdentifier: "SecondVC") as! SecondVC
present(secondVc, animated: true, completion: nil)
}
In Swift 5 and iOS 13
The default modal presentation style is a card. This shows the previous view controller at the top and allows the user to swipe away the presented view controller.
To retain the old style you need to modify the view controller inside of your button's action method like this:
secondVc.modalPresentationStyle = .fullScreen
This is the same for both programmatically created and storyboard created controllers.
I have two modules that I need to connect.
The authorization module, which consists of 1 screen. There is no
controller Navigation on it and it is not in its stack.
Main application. The first screen is the root for the controller
navigation.
How can I implement the transition in case of successful authorization from the authorization screen to the main application in Swift code?
My screen scheme
SOLUTION:
I use this solution for my case:
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "rootVC")
UIApplication.shared.delegate?.window??.rootViewController = vc
view.present(vc, animated: true) {
self.view.dismiss(animated: false, completion: nil)
}
Give storyboardId "nav" to the Navigation Controller and then present it on your login view controller.
if let nav = self.storyboard?.instantiateViewController(withIdentifier: "nav") {
self.present(nav, animated: true, completion: nil)
}
on your navigation Controller on storyboard add your storyboard Id, for example I have named it as navController
In your code, from you want to show as the navigation controller as present, add this line
case if presented view Controller on same storyboard
if let navController = self.storyboard?.instantiateViewController(withIdentifier: "navController") {
self.present(navController, animated : true, completion : nil)
}
case if presented view controller on different storyboard
let storyboard = UIStoryboard(name : STORYBOARD_NAME, bundle : nil)
let nav = storyboard.instantiateViewController(withIdentifier: "navController")
self.present(navController, animated : true, completion : nil)
I was able to create an iOS application in which you could switch between views with buttons. These views had a navigation controller so you could go back.
However I want to adapt this slightly.
Instead I want to have a single view start with no navigation controller.
Then when a cell in my table view is clicked, I want to navigate to the next view which has a navigation controller.
I can make this happen using segue in the interface builder but I don't want to manage it through the builder. This is because I only want to go to the next view when I have done some checking on the cell clicked in the table view.
So basically I need to programmatically change views.
Here is what I have done so far:
I have an ordinary View Controller.
I then have next to it a Navigation Controller which is linked to a new View Controller after that.
I gave this View a storyboard ID of presetController.
I then have the below code in my table cell onclick function:
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let nextViewController = storyBoard.instantiateViewController(withIdentifier: "presetController") as! PresetNavigationController
self.present(nextViewController, animated:true, completion:nil)
Now this code takes me to the next view, but no navigation controller is loaded.
How can I make the navigation controller link to this view? It already is embedded to it via the editor tab link.
Photo to explain story board:
StoryBoard
You need to swap View Controller with Navigation Controller and then do this code:
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let nextViewController = storyBoard.instantiateViewController(withIdentifier: "presetController") as! PresetNavigationController
self.present(nextViewController, animated:true, completion:nil)
this will make your navigationbar back button appear
If your link Navigation controller from New controller and Your are opening presntview controller than you will be make as this
let nextViewController = storyBoard.instantiateViewController(withIdentifier: "presetController") as! PresetNavigationController
let navController = UINavigationController(rootViewController: nextViewController)
self.present(navController, animated:true, completion: nil)
Using the suggestions from ppinho I put the navigation controller as the entry point.
As I did not want the navigation controller on the first view I hid it with the below code:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Hide the navigation bar on the this view controller
self.navigationController?.setNavigationBarHidden(true, animated: animated)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// Show the navigation bar on other view controllers
self.navigationController?.setNavigationBarHidden(false, animated: animated)
}
I then added the new view to the navigation like so:
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let nextViewController = storyBoard.instantiateViewController(withIdentifier: "presetController") as! PresetViewController
self.navigationController?.pushViewController(nextViewController, animated: true)
Here it is
let nextScreen = storyboard?.instantiateViewController(withIdentifier: "nextScreenIdentifier") as! NextScreenControllerName
self.navigationController?.pushViewController(nextScreen, animated: true)
write this inside any function of the viewcontroller.
I have a few view controllers with navigation bar and tab bar. Then I have an initial view controller with no navigation bar and tab bar. I want to go back to the initial view controller with no other view controllers in stack. Here's what I do:
// Head back to Initial View Controller.
let initialViewController = self.storyboard!.instantiateViewController(withIdentifier: "Initial")
UIApplication.shared.keyWindow?.rootViewController = initialViewController
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window?.rootViewController = initialViewController
This works perfectly. But then it doesn't move to another view controller from the initial view controller again. For example:
#IBAction func loginButton(_ sender: Any) {
print("Login Button Tapped.")
let storyboard = UIStoryboard(name: "SignInViewController", bundle: nil)
let signInViewController = storyboard.instantiateViewController(withIdentifier: "SignInViewController") as! SignInViewController
self.navigationController?.show(signInViewController, sender: nil)
}
Here, the print statement is run, but self.navigationController.show won't. How do all this work? And what's the right approach to accomplish this?
EDIT:
To avoid any confusion, here's my storyboard. The left most viewcontroller (pink screen) is the initial view controller I want to go back to. The right most on the same level is the view where I want to go back from.
It doesn't move to another view controller, because you are setting a simple view controller in your rootViewController.
What you need is:
let initialViewController = self.storyboard!.instantiateViewController(withIdentifier: "Initial")
let navController = UINavigationController.init(rootViewController: initialViewController)
UIApplication.shared.keyWindow?.rootViewController?.present(navController, animated: true, completion: nil)
This will create a navigationviewcontroller, so when on "Initial" you should be able to perform push, present actions of another view controllers.
From your initial view controller, you need to instantiate your navigation stack and present it modally. Then, when you want to get back to your pre-navigation initial VC, just call dismiss(animated:,completion:), which will dismiss your entire navigation stack and return you to the initial view controller.
self.navigationController.popToRootViewController(animated:) is what you're looking for.
https://developer.apple.com/documentation/uikit/uinavigationcontroller/1621855-poptorootviewcontroller
EDIT
Try dismissing the navigationController after calling popToRoot.
self.navigationController.dismiss(animated: true, completion: nil)
EDIT
Try the following:
#IBAction func loginButton(_ sender: Any) {
print("Login Button Tapped.")
let storyboard = UIStoryboard(name: "SignInViewController", bundle: nil)
let signInViewController = storyboard.instantiateViewController(withIdentifier: "SignInViewController") as! SignInViewController
present(signInViewController, animated: true, completion: nil)
//self.navigationController?.show(signInViewController, sender: nil)
}
Then to dismiss the signInViewController call self?.navigationController.dismiss(animated:true, completion:nil) from inside the signInViewController.
I'm trying to switch from one UIViewController to another using code. Right now I have,
self.presentViewController(ResultViewController(), animated: true, completion: nil)
All this is doing is taking me to a black screen instead of the ResultViewController. Any suggestions?
With Storyboard. Create a swift file (SecondViewController.swift) for the second view controller
and in the appropriate function type this:
let secondViewController = self.storyboard?.instantiateViewController(withIdentifier: "secondViewController") as! secondViewController
self.navigationController.pushViewController(secondViewController, animated: true)
Without storyboard
let secondViewController = ViewController(nibNameOrNil: NibName, bundleOrNil: nil)
self.presentViewController(secondViewController, animated: true, completion: nil)
You can try this one
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let resultViewController = storyBoard.instantiateViewControllerWithIdentifier("ResultView") as ResultViewController
self.presentViewController(resultViewController, animated:true, completion:nil)
Make sure you set your view controller identifier.
Swift 3
To present a controller modally
let vc = self.storyboard!.instantiateWithIdentifier("SecondViewController")
self.present(vc, animate: true, completion: nil)
To show a controller
self.show(vc, sender: self)
Try this:
let vc = ViewController(nibNameOrNil: yourNibName, bundleOrNil: nil)
self.presentViewController(vc, animated: true, completion: nil)
Hope this helps.. :)
The easiest way to do this would be to create a segue by right clicking on the view you are starting on and dragging the blue line to the result view controller the hit the show segue option. Then set the identifier of the segue to "segue". Now add this code wherever you would like in your view controller:
self.performSegueWithIdentifier("segue", sender: nil)
this will trigger the segue that will go to your resultViewController
The easiest way to switch between screens in iOS is. Add a button on the current screen. Then press control and drag the button to the target screen. Then select push. And when you will tap the button the screen will be switched to the target screen.
Make sure you are using a UINavigationViewController.
Source: ios UINavigationController Tutorial.
Shaba's answer is a good start but requires the following so that you
can control the segue from within your view controller:
override func shouldPerformSegue(withIdentifier identifier: String,
sender: Any?) -> Bool {
// your code here
// return true to execute the segue
// return false to cause the segue to gracefully fail }
Source
vc = YourViewController()
UIApplication.shared.keyWindow?.rootViewController = vc
Or
vc = YourViewController()
UIApplication.shared.keyWindow?.rootViewController = UINavigationController(rootViewController: vc) //If you want to add navigation functionality to that VC