how could i dismiss a view controller that i call it by using this method
func openUpgradeAccount(){
let appdel = AppDelegate.sharedInstance()
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let earnFreeSpace = storyboard.instantiateViewControllerWithIdentifier("IAPUpgradeVC") as! IAPUpgradeVC
let navigation:UINavigationController = UINavigationController(rootViewController: earnFreeSpace)
appdel.drawerController!.mainViewController = navigation
appdel.drawerController!.setDrawerState(.Closed, animated: true)
}
in this controller i add UIBarButtonItem to cancel id viewdidload method
let cancelBarBtn = UIBarButtonItem(title: NSLocalizedString("Cancel", tableName: appLocalizedTable, comment: ""), style: UIBarButtonItemStyle.Done, target: self, action: #selector(IAPUpgradeVC.didTapCancelButton(_:)))
cancelBarBtn.tintColor = UIColor.whiteColor()
self.navigationItem.leftBarButtonItem = cancelBarBtn
the didTapCancelButton method that i use to dismiss the view was
func didTapCancelButton(sender: UIBarButtonItem) {
self.dismissViewControllerAnimated(true) { () -> Void in
}
but when i tap cancel button nothing happen , what i want how can i return back to the last ViewController , can anyone help me ?
First of all, what is the drawerController? What's its superclass and what's its mainViewController supposed to be?
The method that you call when tapping the button is for dismissing a view controller presented modally. However before that, you do not present that view controller modally, setting is as drawerController's mainViewController instead:
appdel.drawerController!.mainViewController = navigation
One way to make it work is to change this line, so that instead of setting mainViewController you call presentViewController to present the new view controller modally.
If that is not how you want it to work (no presentation of view controllers), you'd have to elaborate on what you want both the new vc and the drawerController to do.
Related
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)
When the function is done executing I want to go back to my ProfileTabViewController. I want to get sent back to the view controller keeping the ProfileTabViewControllers same navigation bar and UITabBarController from before. The way I have it now it gets sent to the ProfileTavViewController but I lose my navigation bar as well as the tab bar. How do I just send it back to the original ProfileTabViewController. The first image is the original ViewController and the second image is when it gets sent back.
#IBAction func updateAction(_ sender: Any) {
let newInterests = options.joined(separator: " , ")
if newInterests == ""{
showAlert(message: "Please select at least one interest.")
}else{
updateFunction()
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "ProfileTabViewController") as! UIViewController
self.navigationController?.present(vc, animated: true, completion: nil)
}
}
While Presenting a ViewController it will not show navigationbar beacause presentation depends on UIViewController not NavigationViewcontroller.
You have to use popViewController method to get navigation bar.
for controller in self.navigationController?.viewControllers {
if controller is ProfileViewController {
self.navigationController!.popToViewController(controller, animated: true)
break
}
}
//Use Pop
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 have a view controller as my initial view controller.
there's a button in it(GO button) which when the user taps, it should go to another view controller(let's call it Destination view controller with label 'This is where i wanna go'). Meanwhile i want to pass it through a Tabbar controller. The reason is i want to have tabbar in my navigation stack and when users presses back on Destination view controller, it must go to tabbar controller. Picture shows what i want. what can I do to skip tabbar while having it in navigation stack?
You can do that easily inside the IBAction of GO button:
#IBAction func goTapped(_ sender: UIButton) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc1 = storyboard.instantiateViewController(withIdentifier: "myTabBarViewController")
let vc2 = storyboard.instantiateViewController(withIdentifier: "myGoalViewController")
let controllers = [vc1, vc2]
self.navigationController!.setViewControllers(self.navigationController!.viewControllers + controllers, animated: true)
}
Good luck!
Going to DestinationViewController could be manually:
if let destinationViewController = self.storyboard?.instantiateViewController(withIdentifier: "Storyboard ID of DestinationViewController") {
self.navigationController?.pushViewController(destinationViewController, animated: true)
}
(Alternatively, you could make a segue from FirstViewController to the DestinationViewController directly in Storyboard)
And in your DestinationViewController, insert the TabbarController to the Navigation sequence manually after view did appear, then you are able to go back to the TabbarController:
class DestinationViewController: UIViewController {
//......
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if self.isBeingPresented || self.isMovingToParentViewController {
var viewControllers = self.navigationController?.viewControllers
if let index = viewControllers?.endIndex.advanced(by: -1),
let tabBarController = self.storyboard?.instantiateViewController(withIdentifier: "Storyboard ID of TabBarController") {
viewControllers?.insert(tabBarController, at: index)
self.navigationController?.viewControllers = viewControllers!
}
}
}
//......
}
I am using Xib instead of storyboard and using this code in my AppDelegate to perform navigation in my project
var nav = UINavigationController()
let FirstVC = HomeScreenVIewController(nibName: "HomeScreenVIewController", bundle: nil) as HomeScreenVIewController
nav = UINavigationController(rootViewController: FirstVC)
nav.navigationBarHidden = true
self.window?.rootViewController = nav
self.window?.makeKeyAndVisible()
nav.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .Plain, target: nil, action: nil)
To navigate from one view to other on button click I am using this code
let NextVc = RegistrationStepOneViewController(nibName: "RegistrationStepOneViewController", bundle: nil) as RegistrationStepOneViewController
appDelegate.nav.pushViewController(NextVc, animated: true)
This navigation will go for all registration process steps. When registration is completed there is a dashboard screen from where user can not navigate back to registration steps(obviously).
Now I want another navigation to start from dashboard and go futher in the application. How can I do that ?
Thanks in advance :-)
You can use the setViewControllers: animated: method to replace the current navigation stack with whatever stack you'd like.
self.navigationController?.setViewControllers([yourNewRootVC], animated: true)
The above, for example, would give you a new root controller and would blow up your current nav stack.
Having said that, with the situation you are describing, I would recommend launching the app with the main view controller as the root of your nav VC, then presenting (animated: false) the registration flow over that. Then you just need to dismiss it once registration is complete or not present it at all if registration has already happened. Hope that makes sense!
You can do something like,
let vc: UIViewController = UIViewController()
let view: UIView = UIView(frame: CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height))
vc.view = view
vc.view.backgroundColor = UIColor.orangeColor()
let arr: [UIViewController] = [vc as UIViewController]
self.navigationController!.setViewControllers(arr, animated: true)
You can set array of viewcontrollers to navigation controller. You can add multiple array to that arr and can use same navigation controller.