I am newbie with Swift and I have to manage multiple child view controllers in one UIContainerView with storyboard layout but, container view only provide one child view at once.
I have already used below code:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
var controller: UIViewController = storyboard.instantiateViewControllerWithIdentifier("HomeVC") as UIViewController
self.containerViewA.addSubview(controller.view)
self.addChildViewController(controller)
In ios at a container view only connect with one child controller "at a time" , instead of child view controller we can take one UINavigationController with its RootviewControlle, We can load multiple child view controller using multiple UINavigationController as mentioned below.
var navController1 = UINavigationController()
var navController2 = UINavigationController()
var navController3 = UINavigationController()
var navController4 = UINavigationController()
override func viewDidLoad()
{
super.viewDidLoad()
//navController1
let VC1 = self.storyboard!.instantiateViewControllerWithIdentifier("HomeVC") as! HomeVC
navController1 = UINavigationController(rootViewController: VC1)
navController1.navigationBarHidden = true
//navController2
let VC2 = self.storyboard!.instantiateViewControllerWithIdentifier("RoomControlesVC") as! RoomControlesVC
navController2 = UINavigationController(rootViewController: VC2)
navController2.navigationBarHidden = true
//navController3
let VC3 = self.storyboard!.instantiateViewControllerWithIdentifier("TelevisionVC") as! TelevisionVC
navController3 = UINavigationController(rootViewController: VC3)
navController3.navigationBarHidden = true
//navController4
let VC4 = self.storyboard!.instantiateViewControllerWithIdentifier("EntertainmentVC") as! EntertainmentVC
navController4 = UINavigationController(rootViewController: VC4)
navController4.navigationBarHidden = true
let btn = UIButton()
btn.tag = 1
self.ActionOnSideMenuButtons(btn)
}
#IBAction func ActionOnSideMenuButtons(sender: AnyObject)
{
for view in containerViewA.subviews{
view.removeFromSuperview()
}
switch sender.tag
{
case 1:// Home
NSLog("Home Button tapped")
addChildViewController(self.navController1)
self.navController1.view.frame = self.containerViewA.bounds
self.containerViewA.addSubview(navController1.view)
break
case 2:// Room Controles
NSLog(" Room Controles Button tapped")
self.navController2.view.frame = self.containerViewA.bounds
self.containerViewA.addSubview(navController2.view)
break
case 3:// Television
NSLog("Television Button tapped")
self.navController3.view.frame = self.containerViewA.bounds
self.containerViewA.addSubview(navController3.view)
break
case 4:// Entertainment
NSLog("Entertainment Button tapped")
self.navController4.view.frame = self.containerViewA.bounds
self.containerViewA.addSubview(navController4.view)
break
default:
break
}
}
In above code i have created 4 navigation controllers and initialise them in viewDidLoad method & on "ActionOnSideMenuButtons" method i have load childview controller whenever any of side menu button tapped.
Related
I am failing to understand the fundamentals of what is needed to add my HomeViewController (UIViewController) as one of the tabs in my homeTabBarController (UITabBarController) using the setViewControllers method.
I have tried initializing this and simply adding it as a param in the method. There seems to be a difference between a view controller created via storyboard and one created programmatically because when I tried adding a viewcontroller:UIViewController programmatically to the setViewControllers method, it worked fine.
My code below compiles however I get a runtime exception Thread 1: EXC_BAD_ACCESS (code=2, address=0x7ff7b8491598) at the line when homeTabBarController.setViewControllers is called
`
func loadTabBar() {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let homeViewController = storyboard.instantiateViewController(identifier: Constants.Storyboard.homeViewController) as? HomeViewController
homeViewController!.title = "Home"
homeTabBarController.setViewControllers([homeViewController!], animated: false)
homeTabBarController.modalPresentationStyle = .fullScreen
present(homeTabBarController, animated: true)
}
`
//MARK: - Create the instances of ViewControllers
let grayViewController = HomeViewController()
let blueViewController = FirstViewController()
let brownViewController = SecondViewController()
override func viewDidLoad() {
super.viewDidLoad()
//set title of the viewcontrollers
grayViewController.title = "home"
blueViewController.title = "first"
brownViewController.title = "second"
//Assigne the viewcontrollers to the TabBarViewController
self.setViewControllers([ grayViewController, blueViewController, brownViewController], animated: false)
//set system images to each tabBars
guard let items = self.tabBar.items else {
return
}
let images = ["house.fill", "star.fill", "bell.fill"]
for i in 0...2 {
items[i].image = UIImage(systemName: images[i])
}
self.tabBar.tintColor = .black
}
// You can download the project from the below github link
https://github.com/ahmetbostanciklioglu/AddingTabBarControllerProgrammatically.git
I have a UITabBarController which has 4 tabs. I want to show different view controllers for second tab bar item. Depending on the condition I want to show the view controllers for that tab bar item.
I wrote following code :
UITabbarController -
override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
if item.tag == 2 {
if UserDefaults.standard.bool(forKey: "FirstTimeUser") == true {
// let vc1 = storyboard?.instantiateViewController(identifier: "CreateNewProjectViewController") as! CreateNewProjectViewController
// self.navigationController?.pushViewController(vc1, animated: true)
let vc1 = self.storyboard?.instantiateViewController(withIdentifier: "CreateNewProjectViewController") as! CreateNewProjectViewController
let window = UIApplication.shared.windows.first
window?.rootViewController = vc1
tabBarController?.tabBar.isHidden = false
}else {
// let vc2 = storyboard?.instantiateViewController(identifier: "ProjectsViewController") as! ProjectsViewController
// self.navigationController?.pushViewController(vc2, animated: true)
let vc2 = self.storyboard?.instantiateViewController(withIdentifier: "ProjectsViewController") as! ProjectsViewController
let window = UIApplication.shared.windows.first
window?.rootViewController = vc2
tabBarController?.tabBar.isHidden = false
}
}
}
I tried with navigationController but it is showing blank screen.
If I try setting the view controller with "
let vc2 = self.storyboard?.instantiateViewController(withIdentifier: "ProjectsViewController") as! ProjectsViewController
let window = UIApplication.shared.windows.first
window?.rootViewController = vc2
tabBarController?.tabBar.isHidden = false
".
It does not show the tab bar, please help me get it correctly.
Thank you!
I have implemented a tabBar programmatically:
class ViewController: UIViewController {
let tabBarCnt = UITabBarController()
override func viewDidLoad() {
super.viewDidLoad()
tabBarCnt.tabBar.tintColor = UIColor.black
createTabBarController()
}
func createTabBarController() {
let firstVc = UIViewController()
let downloadViewController = DownloadsViewController()
downloadViewController.tabBarItem = UITabBarItem(tabBarSystemItem: .downloads, tag: 0)
let bookmarkViewController = BookmarksViewController()
bookmarkViewController.tabBarItem = UITabBarItem(tabBarSystemItem: .bookmarks, tag: 1)
let favoritesViewControllers = FavoritesViewController()
favoritesViewControllers.tabBarItem = UITabBarItem(tabBarSystemItem: .favorites, tag: 2)
// Adding navigationControllers
let controllerArray = [downloadViewController, bookmarkViewController, favoritesViewControllers]
// For somereason this made the word Home appear in first tab
tabBarCnt.viewControllers = controllerArray.map{ UINavigationController.init(rootViewController: $0)}
self.view.addSubview(tabBarCnt.view)
}
}
DownloadViewController.swift
class DownloadsViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.green
self.title = "Downloads"
}
}
This is the result:
MY QUESTION IS:
Do I have to implement all the layouts of the different viewControllers downloadViewController, bookmarkViewController, favoritesViewControllers programmatically?
Can't I use the storyboard and associate a viewController and do all the UI design and implementation there like this:
The problem here is that if I will implement all the layout programmatically, it won't be an obvious or a practical thing to do.
And assigning DownloadsViewController to that storyboard ViewController, doesn't make it get display it when I navigate to DownloadsTab in the UITabBar.
Yes, you can do that currently your creating view controller instance programmatically, instead of that you have to load/get viewController instance from storyBoard like this.
UIStoryboard(name: "Main", bundle: Bundle.main).instantiateViewController(identifier: "downloadsVC") as! DownloadsViewController
before calling this method set viewController StoryboardID
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
I have a tab bar, whose items I want to change depending on a user's settings. So I need to be able to add/remove items from the tab bar programmatically. Here is my code:
class TabBarViewController: UITabBarController {
var controllerArray = [UIViewController]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.tabBar.tintColor = UIColor.greenColor()
let storyBoard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())
let controller1 = storyBoard.instantiateViewControllerWithIdentifier("Navigation2") as! nav2
let controller2 = storyBoard.instantiateViewControllerWithIdentifier("Explore") as! ExploreNavigation
let controller3 = storyBoard.instantiateViewControllerWithIdentifier("friends") as! ExploreNav
let controller4 = storyBoard.instantiateViewControllerWithIdentifier("controller3ID") as! controller3VC
controllerArray.append(controller1)
controllerArray.append(controller2)
controllerArray.append(controller3)
controllerArray.append(controller4)
self.tabBarController?.setViewControllers(controllerArray, animated: true)
}
}
but if I comment out one of the lines, for example like this:
//controllerArray.append(controller2)
so that that controller is not apart of the controllersArray, the controller still displays in the tab bar. What am I doing wrong?
I also tried this, and it didn't work either:
self.tabBarController?.viewControllers = controllerArray
Just say
self.setViewControllers(controllerArray, animated: true)
instead of
self.tabBarController?.setViewControllers(controllerArray, animated: true)
You are subclassing UITabBarController not UIViewController so you don't have, or at least don't need, the property tabBarController.