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)
}
}
Related
When a push notification is received, I am trying to navigate to a table view controller (ReportTVC). The Hierarchy of the view controllers in my storyboard is as shown below.
TabBarController -> Navigation Controller (Storyboard ID: CasesNavController) -> TableViewController (CasesTVC) -> TableViewController (CaseSummaryTVC) -> TableViewController(ReportTVC)
The ReportTVC is being displayed with the navigation controller as expected, but when I navigate back to the CasesTVC, I should have a TabBar with the tabs, but this is missing.
Can someone please advise how I could resolve this ?
In AppDelegate.swift:
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let navController = mainStoryboard.instantiateViewController as! UINavigationController
let reportTVC = mainStoryboard.instantiateViewController(withIdentifier: "ReportTVC") as! ReportTVC
reportTVC.obtainDoctorReport = true
reportTVC.caseId = caseId
navController.pushViewController(reportTVC, animated: true)
self.window?.rootViewController = navController
self.window?.makeKeyAndVisible()
The problem here is that you're setting the NavigationController to the as rootViewController you need to set the TabBarController as the root.
let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
let navController = mainStoryboard.instantiateViewController(withIdentifier: "Nav") as! UINavigationController
let tabController = mainStoryboard.instantiateViewController(withIdentifier: "Tab") as! UITabBarController
let reportTVC = mainStoryboard.instantiateViewController(withIdentifier: "ReportTVC") as! ReportTVC
reportTVC.obtainDoctorReport = true
reportTVC.caseId = caseId
navController.pushViewController(reportTVC, animated: true)
tabController.setViewControllers([navController], animated: false)
self.window?.rootViewController = tabController
self.window?.makeKeyAndVisible()
You shouldn't forget that you also need the add the other ViewControllers in the TabBarViewController.
I would like to jump from a viewController to the first viewController related to Tab Bar Controller through code.
The tabBarController Scene has storyboard id tabView.
I'm working on this way:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc: UITabBarController!
storyboard.instantiateViewController(withIdentifier: "tabView")
vc=storyboard.instantiateViewController(withIdentifier: "tabView") as! UITabBarController
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
self.present(vc as! UIViewController, animated: true, completion: nil)
}
But it loads only the first viewController (out of 5) without the tab bar related to. How can I solve it?
Oh, this code looks so wrong.
In your storyboard give and "tabView" ID to the TabBarController, not the ViewController inside it.
Why you are double instantiating ViewController? just do it once and assign it to the vc variable.
Why you've created delay before presenting the VC? It's some sort of workaround of something?
Working code:
let vc = storyboard.instantiateViewController(withIdentifier: "tabView") as! UITabBarController
self.present(vc, animated: true)
Use
(1)if you want to navigate from Appdelegate
let appDelegate = UIApplication.sharedApplication.delegate as! AppDelegate
let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
let tabBar = mainStoryboard.instantiateViewControllerWithIdentifier("TabBarController") as! TabBarController
appDelegate.window?.rootViewController = tabBar
appDelegate.window?.makeKeyAndVisible()
(2)if you want to navigate from viewcontroller which has root of navigation
self.navigationController?.pushViewController(tabBar, animated: true)
I wonder how I can check what view controller that is currently displayed.
When a user recivies a notification and press on it I want to take the user to a certain VC. But only if the user is not already there.
I am using this when I get a notification:
if let tabBarController = self.window!.rootViewController as? CustomTabBarController {
let navInTab:UINavigationController = tabBarController.viewControllers?[0] as! UINavigationController
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let destinationViewController = storyboard.instantiateViewController(withIdentifier: "EventVc") as? EventsViewController
navInTab.pushViewController(destinationViewController!, animated: true)
tabBarController.selectedIndex = 0
}
I dont want to run this code if the user already is in EventVc
Also, can I run the code above if the user already is in tab 0 but in a different VC than EventVc?
And if it is any help my app is built like this:
(root) TabBar
(tab1) -> navigation controller -> vc -> vc...
(tab2) -> navigation controller -> vc -> vc...
(tab3) -> navigation controller -> vc -> vc...
(tab4) -> navigation controller -> vc -> vc...
this function should solve your problem, just send index number as an argument (forexample: 0 for tab1, 1 for tab2 etc.) at it navigates you selectedIndex ViewController.
// Navigation TabIndex TabBar View Controller
fileprivate func goTabIndex(index: Int) {
let storyboard = UIStoryboard(name: "yourTabbarStoryboardID", bundle: nil)
let tabBarController = storyboard.instantiateViewController(withIdentifier: "EventVc") as! UITabBarController
tabBarController.selectedIndex = index
self.window?.makeKeyAndVisible()
DispatchQueue.main.async {
self.window?.rootViewController?.present(tabBarController, animated: false)
}
}
You can find the Presenting ViewController like this;
let presentingVC = self.window?.rootViewController?.presentingViewController
Presented ViewController;
let presentedVC = self.window?.rootViewController?.presentedViewController
I want to segue from AppDelegate to First View of UITabBarController.
I assigned StoryBoardID of UITabBarController as "HomePage".
and I tried below code:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let viewController: UITabBarController = storyboard.instantiateViewControllerWithIdentifier("HomePage") as! UITabBarController
let rootViewController = self.window!.rootViewController as! UINavigationController
rootViewController.pushViewController(viewController, animated: true)
It works but I gave BackBarButton on destination view which I don't want.
I want to segue Presently.
You need to set your viewControllers instead of pushViewController
rootViewController.viewControllers = [viewController]
Instead of
rootViewController.pushViewController(viewController, animated: true)
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