Load view controller from another controller - ios

I am using this code to load view controllers inside a container in ViewController without using any segue.
Example:
let newViewController =self.storyboard?.instantiateViewController(withIdentifier: "FBViewController")
newViewController!.view.translatesAutoresizingMaskIntoConstraints = false
self.cycleFromViewController(oldViewController: self.currentViewController!, toViewController: newViewController!)
self.currentViewController = newViewController
This code is working for any controller but in one case where i need to load a controller called FBViewController and in its ViewDidLoad i check if the user is logged, in case he is i want to load another controller instead of theFBViewController immediately.
I tried this code inside the viewDidLoad of FBViewController:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "userProfilePage")
self.present(controller, animated: true, completion: nil)
I tried calling a method in the main view controller to load the wanted view:
let otherViewController: ViewController = ViewController()
otherViewController.loggedIn()
Method:
func loggedIn(){
let newViewController = self.storyboard?.instantiateViewController(withIdentifier: "userProfilePage")
newViewController!.view.translatesAutoresizingMaskIntoConstraints = false
self.cycleFromViewController(oldViewController: self.currentViewController!, toViewController: newViewController!)
self.currentViewController = newViewController
}
None of them worked. I appreciate any help.

You can try the following inside MainViewController:
var newViewController : UIViewController
if loggedIn == true {
newViewController = self.storyboard?.instantiateViewController(withIdentifier: "userProfilePage")
} else {
newViewController = self.storyboard?.instantiateViewController(withIdentifier: "FBViewController")
}
newViewController!.view.translatesAutoresizingMaskIntoConstraints = false
self.cycleFromViewController(oldViewController: self.currentViewController!, toViewController: newViewController!)
self.currentViewController = newViewController

The code you have should work, just go to your storyboard and select the controller you want to call. Then make sure that under storyboard ID you have the same name that you are using to call it.

Related

Transition to MainVC gives the empty View without subviews

I'm using this type of transition to UIViewcontroller:
self.navigationController?.popToViewController(MainVC(), animated: false)
And in result i want to receive the MainVC with all subviews... but i receive only empty main View without any subviews. What i did wrong?
Update:
I have the transition to MainVC, but it's empty, only initial View, without all subviews. What is the reason?
You should pass object of MainVC()
like below
let objOfMainVC = MainVC()
self.navigationController?.popToViewController(objOfMainVC, animated: false)
If you are using storyboard then
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let main = storyBoard.instantiateViewController(withIdentifier: "MainVC") as! MainVC // set withIdentifier to your identifier that was set in your storyboard.
self.navigationController?.pushViewController(main, animated: false)
You need the reference of MainVC. You can't just create a new instance of MainVC()
if let viewControllers = self.navigationController?.viewControllers {
for vc in viewControllers {
if let _ = vc as? MainVC {
self.navigationController?.popToViewController(vc, animated: true)
break
}
}
}
Or if your MainVC is root view controller of navigation controller.
self.navigationController?.popToRootViewController(animated: true)

How can I show ViewController in UITabBarController?

I have a UITabBarController and all my other view controllers are connected to it. Now I want to show one my controller as:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc: ViewController = storyboard.instantiateViewControllerWithIdentifier("ViewController") as! ViewController
but when I tried to:
let rootViewController = self.window?.rootViewController as! UINavigationController
rootViewController.pushViewController(vc, animated: true)
it gave me the next error:
Could not cast value of type 'UITabBarController' (0x1a899b818) to 'UINavigationController'
Later I've tried to do:
let rootViewController = self.window?.rootViewController as! UITabBarController
but in this case I get
UITabBar has no member pushViewController
How can I show/push my ViewController so it will appear with UINavigationBar and inside of UITabBar?
You need to place each of your view controllers inside a navigation controller.
E.g. currently you have a TabBarViewController
and two view controllers:
ViewControllerA
ViewControllerB
What you need to do is to embed each of them inside a navigation controller so you would have:
UINavigationController -> ViewControllerA
UINavigationController -> ViewControllerB
In order to push a new controller you would do:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc: ViewController = storyboard.instantiateViewControllerWithIdentifier("ViewController") as! ViewController
let navViewController = myTabBar.selectedViewController as? UINavigationController
navViewController?.pushViewController(vc, animated: true)
Could not cast value of type 'UITabBarController' (0x1a899b818) to 'UINavigationController'
Your root view controller is of type UITabBarController.
Therefore you have to use the appropriate methods of this class and not UINavigationController.
To set view controllers use either
var viewControllers: [UIViewController]? or
func setViewControllers([UIViewController]?, animated: Bool).
To have a navigation bar you have to instantiate a UINavigationController and add your view controller to this navigation controller.
Then add your navigation controller to your UITabBarController with via one of the above options.
If your class is UITabBarController
You can add this:
private func showViewController() {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
guard let vc = storyboard.instantiateViewController(withIdentifier: "queueTableViewController") as? QueueTableViewController else { return }
let navVC = self.selectedViewController as? UINavigationController
navVC?.pushViewController(vc, animated: true)
}
This will allow you to go to any VC
The second solution is something like this.
Here You will show the last VC and from there push some VC.
guard let tabCount = viewControllers?.count, tabCount > 1 else { return }
selectedIndex = tabCount - 1
if let navigationController = viewControllers?[selectedIndex] as? UINavigationController {
if let accountVC = navigationController.visibleViewController as? FirstViewController {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
guard let vc = storyboard.instantiateViewController(withIdentifier: "someViewController") as? SomeViewController else { return }
accountVC.navigationController?.pushViewController(vc, animated: true)
}
}

How to instantiate a navigation controller from another view controller?

My goal is whenever i click a button on a first view controller, then it will navigate to another controller which is a navigation controller.
firstViewController and secondViewController has no connection or anything.
Picture
I used this code
#IBAction func buttonTapped(sender: UIButton) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("secondViewCtrl") as! SecondViewController
self.presentViewController(vc, animated: true, completion: nil)
}
The reason why i instatiate so that I could pass data like
vc.name = "Myname"
The problem with this code is that it doesn't present navigation bar and as well as the tab bar. What should I do to show both?
Updated question
#IBAction func buttonTapped(sender: UIButton) {
guard let tabBarController = tabBarController else { return }
tabBarController.selectedIndex = 1
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("trackYourGenie") as! TrackYourGenieViewController
let navController = tabBarController.viewControllers![1]
let secondViewController = navController.topViewController
vc.name = "Myname"
}
You are instantiating the view controller hence you wouldn't get the navigation bar. To get the navigation bar please instantiate navigation controller and since the second view is only child you would get the second view by default.
#IBAction func buttonTapped(sender: UIButton) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("Navigation Controller Id") as! UINavigationController
self.presentViewController(vc, animated: true, completion: nil)
}
The above code should give you the navigation bar.
A safe approach:
guard let tabBarController = tabBarController else { return }
tabBarController.selectedIndex = 1
If you need to access to your tabBarController to pass datas you can do simply:
let navController = tabBarController.viewControllers[1]! as! UINavigationController
let secondViewController = navController.topViewController
Your method could be:
#IBAction func buttonTapped(sender: UIButton) {
guard let tabBarController = tabBarController else { return }
let navController = tabBarController.viewControllers[1]! as! UINavigationController
let secondViewController = navController.topViewController as! SecondViewController
secondViewController.name = "my name"
tabBarController.selectedIndex = 1
}
In your case, the following code should be sufficient :
self.tabBarController.selectedIndex = 1
As UITabBarController is your rootViewController, you can access it with self.tabBarController. You don't have to instantiate UINavigationController as it is in the storyboard.
I can see from your StoryBoard that you have a TabBarController. If your configuration is that and FirstViewController is on first tab and SecondViewController on second tab, you can just change TabBarController selectedIndex property:
#IBAction func buttonTapped(sender: UIButton) {
tabBarController?.selectedIndex = 1
}
If you want to pass data to SecondViewController you can try one of these solutions:
let controller = tabBarController.viewControllers[1] as SecondViewController!
controller.data = "some data"
This soultion could not work since SecondViewController is not ready yet.
Create a singleton class where to save data, then retrieve data in SecondViewController viewDidLoad method
Save data in UserDefaults, then retrieve data in SecondViewController viewDidLoad method (bad solution if information doesn't have to be persistent)
Extend UITabBarController and use it, create a custom var in tabBarController, put data in that variable and then retrieve data in SecondViewController viewDidLoad method
Then clear data if needed.
Navigation will not work from firstViewController as to navigate something we need UINavigationController.
Try Like This

Dismissing a custom viewcontroller

I'm currently using a third party called "Form".
In my UIButton, I implement a method which initializes a custom view controller which is a subclass of FormViewController. I initialize FormViewController embedded in navigation controller.
In my FormViewController class, I tried below two methods but none of them did not work.
self.navigationController?.popViewControllerAnimated(true)
self.dismissViewControllerAnimated(true, completion: nil)
Codes for pressing a UIButton:
#IBAction func part1Pressed(sender: AnyObject) {
if let JSON = NSJSONSerialization.JSONObjectWithContentsOfFile("data.JSON") as? [String : AnyObject] {
let initialValues = [
"last_name" : "Nordman"]
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let viewContainerVC = storyboard.instantiateViewControllerWithIdentifier("viewContainerVC")
let sampleController = Part1_VC(JSON: JSON, initialValues: initialValues)
let rootViewController = UINavigationController(rootViewController: sampleController)
rootViewController.view.tintColor = UIColor(hex: "5182AF")
rootViewController.navigationBarHidden = false
FORMDefaultStyle.applyStyle()
FORMSeparatorView.appearance().setSeparatorColor(UIColor.clearColor())
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
self.window?.rootViewController = rootViewController
self.window?.makeKeyAndVisible()
}
}
Thank you!
You are trying to dismiss the view controller when it wasn't presented in the first place.
Instead set the root view controller of the navigation controller to something else (e.g. the screen you want shown after you dismiss the form) and present your form view controller modally:
self.presentViewController(formVc, animated: true, completion: nil)
You can then dismiss the view controller as you intended when you are finished with the form.

How do I transition to a different view controllers present in different storyboards programmatically using swift?

let customerStoryboard = UIStoryboard(name: "Customer", bundle: nil) //First(Current) storyboard
let agentStoryboard = UIStoryboard(name: "Agent", bundle: nil) //Second storyboard
var otherVC = UIViewController! // ViewController reference
otherVC = agentStoryboard.instantiateViewControllerWithIdentifier("AgentProfile")
The last statement is not executing or showing results, is anything else required to do other than this?
You only instantiate view controller. To present it you should use presentViewController method
someVC.presentViewController(otherVC, animated: true, completion: nil)
Use this code to show the second view controller.
let otherVC : AnyObject! = self.agentStoryboard.instantiateViewControllerWithIdentifier("AgentProfile")
self.showViewController(otherVC as UIViewController, sender: otherVC)
let secondViewController = self.storyboard.instantiateViewControllerWithIdentifier("SecondViewController") as SecondViewController
self.navigationController.pushViewController(secondViewController, animated: true)

Resources