I have a TabBarCoordinator, thats contains a UITabBarController.
I want to add two UINavigationController (CoinPage and Top/Flop), but only one is showing up in the Tab. I thought I have set up everything the right way and I tried some other stuff but I can not get it to work.
This is my code:
class TabBarCoordinator: Coordinator {
var dependencys: DependencyManager
let tabBarController: UITabBarController
var tabCoordinators = [Tabs: Coordinator]()
var navigationController: UINavigationController
init(navigationController: UINavigationController, persistenceCentral: PersistenceCentral, dependencys: DependencyManager) {
self.tabBarController = UITabBarController()
self.navigationController = navigationController
self.dependencys = dependencys
var controllers: [UIViewController] = []
tabCoordinators[.topFlop] = TopFlopCoordinator(navigationController: navigationController, dependencys: dependencys)
tabCoordinators[.coinPage] = CoinPageCoordinator(dependencys: dependencys, navigationController: navigationController)
let coinPageVC = tabCoordinators[.coinPage]!.navigationController
coinPageVC.tabBarItem = UITabBarItem(title: "Coinpage", image: nil, tag: 0)
let topFlopVC = tabCoordinators[.topFlop]!.navigationController
topFlopVC.tabBarItem = UITabBarItem(title: "Top/Flop", image: nil, tag: 1)
controllers.append(topFlopVC)
controllers.append(coinPageVC)
tabBarController.viewControllers = controllers
tabBarController.tabBar.isTranslucent = false
tabCoordinators[.topFlop]?.start()
tabCoordinators[.coinPage]?.start()
}
func start() {
}
}
I did some research, for example he sets up the tabs in a similar way:
https://medium.com/#satindersingh71/uitabbarcontroller-programmatically-2a3df63607f1
So I do not understand why it is not working.
These 2 lines return the same object
let coinPageVC = tabCoordinators[.coinPage]!.navigationController
let topFlopVC = tabCoordinators[.topFlop]!.navigationController
so the last overwrite settings of the first and it shown lonely , you have to make sure that you create 2 separate navigation objects
Related
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
I want to create tab bar dynamically based on server response. Tab count will change every time. And how to design the views all view have the same design only data will change
suppose you have vc1,vc2,vc3
self.tabBarController.viewControllers = [vc1,vc2,vc3]
Create a separate class for tab bar controller. Create a method there which must return tab bar controller.
In the method, pass an array, on each index it will contains the tab bar name, image, selected image, view controller.
You'll need to make your server call BEFORE you set up the view controller. If it is your first view, you will need to do this in viewdidload and perhaps set up an activity indicator. If not you need to have some sort of loading screen / make your call in the immediately prior to your tabBar.
Put This Method in Utilities Class :
class func setupTabBarController(tabbarController: UITabBarController) {
let hOmeVC = HomePageViewController()
let skriblBoxVC = MySkribViewController()
let searchVC = SearchViewController()
tabbarController.tabBar.isExclusiveTouch = true
tabbarController.view.backgroundColor = UIColor.white
// Creating navigation Controller and putting them in tabBarController because without it we will not be able to push viewController
let homeNavigationController = UINavigationController()
let skriblBoxNavigationController = UINavigationController()
let searchNavigationController = UINavigationController()
tabbarController.viewControllers = []
tabbarController.tabBar.isTranslucent = false
tabbarController.viewControllers = [homeNavigationController, skriblBoxNavigationController, searchNavigationController]
tabbarController.selectedIndex = 0
tabbarController.tabBar.items![0].image = #imageLiteral(resourceName: "tab_home")
tabbarController.tabBar.items![1].image = #imageLiteral(resourceName: "tab_box")
tabbarController.tabBar.items![SBModules.SEARCH.rawValue].image = #imageLiteral(resourceName: "tab_search")
tabbarController.tabBar.items![2].image = #imageLiteral(resourceName: "tab_cart")
tabbarController.tabBar.items![0].selectedImage = #imageLiteral(resourceName: "tab_home_selected")
tabbarController.tabBar.items![1].selectedImage = #imageLiteral(resourceName: "tab_box_selected")
tabbarController.tabBar.items![2].selectedImage = #imageLiteral(resourceName: "tab_search_selected")
tabbarController.tabBar.barTintColor = UIColor.white
tabbarController.tabBar.tintColor = UIColor.tabBarBadgeColorWithAlpha()
tabbarController.tabBar.itemPositioning = .automatic
tabbarController.tabBar.itemSpacing = 2.0
tabbarController.tabBarItem.title = nil
if let items = tabbarController.tabBar.items {
for item in items {
item.title = ""
item.imageInsets = UIEdgeInsetsMake(6, 0, -6, 0);
}
}
}
and class this method form viewController
Like
let tabbarController = UITabBarController()
func loadHomePage() {
Utilities.setupTabBarController(tabbarController: self.tabbarController)
self.updateBadgeValueToCart()
self.window?.rootViewController = self.tabbarController
}
I have created a tab bar controller in storyboard, with 5 tab bar items. I want to remove one view controller programatically from the "viewcontrollers" array of the tab bar stack. I also want the app to be show some other tab item as selected when i remove the above view controller. I have tried with the below code, but its not working.
if let tabBarController = self.storyboard?.instantiateViewController(withIdentifier: "tabbar") as? UITabBarController {
tabBarController.viewControllers?.remove(at: 2)
tabBarController.selectedIndex = 1
}
Reassign viewControllers property without the one you don't want:
if let tabBarController = self.storyboard?.instantiateViewController(withIdentifier: "tabbar") as? UITabBarController {
tabBarController.selectedIndex = 1
var controllers = tabBarController.viewControllers
controllers.remove(at: 2)
tabBarController.viewControllers = controllers
}
Now this code is ok, but the problem is the following line:
let tabBarController = self.storyboard?.instantiateViewController(withIdentifier: "tabbar") as? UITabBarController
This creates a new UITabBarController instance - but you want to access the one that was instantiated by the storyboads and that is presented on the screen. However, without more context it's hard to give you suggestions on how to access it. Considering that you call this code from a viewController directly embedded in the tab bar controller, I would start with this:
if let tabBarController = self.tabBarController {
tabBarController.selectedIndex = 1
var controllers = tabBarController.viewControllers
controllers.remove(at: 2)
tabBarController.viewControllers = controllers
}
Try this:
if let tabBarController = self.storyboard?.instantiateViewController(withIdentifier: "tabbar") as? UITabBarController {
var viewControllers = tabBarController.viewControllers
viewControllers.remove(at: 2)
tabBarController.viewControllers = viewControllers
tabBarController.selectedIndex = 1
}
if let tabBarController = self.tabBarController {
let indexToRemove = 3
if indexToRemove < tabBarController.viewControllers?.count {
var viewControllers = tabBarController.viewControllers
viewControllers?.remove(at: indexToRemove)
tabBarController.viewControllers = viewControllers
}
}
i am trying to keep bottom tab bar in children viewcontroller , my issue when i open children window its open without bottom tabs , how i can keep bottom tabs stuck everywhere in the app ?
this is the class of main tabs window ( landing )
class vc_landingPage: UITabBarController , UITabBarControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
}
//Delegate methods
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
print("Should select viewController: \(String(describing: viewController.title)) ?")
return true;
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let sb2 = UIStoryboard(name: "pools", bundle: nil)
let v1 = sb2.b_pools.instantiateInitialViewController()!
v1.tabBarItem = UITabBarItem( title : "" , image: UIImage(named: "icon-pools-x30"), selectedImage: UIImage(named: "icon-pools-x30-active"))
let sb = UIStoryboard(name: "myProfile", bundle: nil)
let v2 = sb.instantiateInitialViewController()!
v2.tabBarItem = UITabBarItem( title : "" , image: UIImage(named: "icon-profile-x30"), selectedImage: UIImage(named: "icon-profile-x30-active"))
self.viewControllers = [v1,v2]
self.selectedIndex = 1
}
}
Please you must manage the children window in a UINavigationController.
let v1 = sb2.b_pools.instantiateInitialViewController()!
let navi1 = UINavigationController.init(rootViewController: v1)
let v2 = sb.instantiateInitialViewController()!
let navi2 = UINavigationController.init(rootViewController: v2)
self.viewControllers = [navi1,navi2]
Make sure your BOTTOM BAR is not none, make sure it is not set to any of your view controller or your tab bar controller
I am trying to make a template for my app... lets say my app loads the same view controller which has a CollectionView for 4 tabs. According to selected index, I have to load the contents into collection view. I am setting up the tab bar manually from Appdelegate. My question is Is this possible like instantiating same viewcntroller for all 4 tabs of Tabbarcontroller at a time. if yes, how will i know correctly that which index is selected?
Code for tabBarcontroller in Appdelegate
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
let tabBarController = UITabBarController()
let storyboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let firstImage = UIImage(named: "image1")
let secondImage = UIImage(named: "image2")
var controllers = [UIViewController]()
for var i = 0; i < self.myList.count; i++ {
let vc : ViewControllerTwo = storyboard.instantiateViewControllerWithIdentifier("view1") as! ViewControllerTwo
if(i == 0 || i == 3)
{
vc.tabBarItem = UITabBarItem(
title: self.myList[i],
image: firstImage,
tag: i)
controllers.append(vc)
}
else
{
vc.tabBarItem = UITabBarItem(
title: self.myList[i],
image: secondImage,
tag: i)
controllers.append(vc)
}
}
self.tabBarController.viewControllers = controllers
self.window?.rootViewController = self.tabBarController
self.self.window?.rootViewController = self.tabBarController
self.window?.makeKeyAndVisible()
If you set your class as the delegate for your tab bar controller, you will get a call to the didSelectViewController delegate method. You can then use your controllers array to determine the index;
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
let tabBarController = UITabBarController()
tabBarController.delegate = self
func tabBarController(_ tabBarController: UITabBarController,
didSelectViewController viewController: UIViewController) {
if let index = self.controllers.indexOf(viewController) {
// Do something with index
}
}