0

I'm using a custom UITabBarController based on Pavel Bogart solution : quite simple, useful and perfect for what I need to do. Unless for 1 thing I don't know how to manage : How to switch programmatically from 1 VC to another (so, without touch tabBar items).

I tried some funcs with selectedIndex = X, modalPresentationStyle = .fullScreen, but nothing really concrete that can be done exactly as we just touch items on UITabBarController.

Here is the code :

class MainTabBarController: UITabBarController {

override func viewDidLoad() {
    super.viewDidLoad()
    setupTabBar()

}

var TabControllers = [VC1(), VC2(), VC3(), VC4(), VC5()]

func setupTabBar(){
    tabBar.backgroundColor = Theme.navBarBackgroundColor
    tabBar.isTranslucent = true
    tabBar.clipsToBounds = true
    
    let screen1 = createNavController(vc: TabControllers[0], selected: #imageLiteral(resourceName: "img1on"), unselected: #imageLiteral(resourceName: "img1off"), label: "Name1")
    let screen2 = createNavController(vc: TabControllers[1], selected: #imageLiteral(resourceName: "img2on"), unselected: #imageLiteral(resourceName: "img2off"),  label: "Name2")
    let screen3 = createNavController(vc: TabControllers[2], selected: #imageLiteral(resourceName: "img3on"), unselected: #imageLiteral(resourceName: "img3off"),  label: "Name3")
    let screen4 = createNavController(vc: TabControllers[3], selected: #imageLiteral(resourceName: "img4on"), unselected: #imageLiteral(resourceName: "img4off"),  label: "Name4")
    let screen5 = createNavController(vc: TabControllers[4], selected: #imageLiteral(resourceName: "img5on"), unselected: #imageLiteral(resourceName: "img5off"),  label: "Name5")
    
    viewControllers = [screen1, screen2, screen3, screen4, screen5]
    
    guard let items = tabBar.items else { return }
    for item in items {
        let unselectedItem = [NSAttributedString.Key.foregroundColor: Theme.darkTextColor]
        let selectedItem = [NSAttributedString.Key.foregroundColor: Theme.mainAccentColor]
        let attributes = [NSAttributedString.Key.font: UIFont(name: Theme.subTitle, size: 16)]
        item.setTitleTextAttributes(attributes as [NSAttributedString.Key : Any], for: .normal)
        item.setTitleTextAttributes(attributes as [NSAttributedString.Key : Any], for: .selected)
        item.setTitleTextAttributes(unselectedItem as [NSAttributedString.Key : Any], for: .normal)
        item.setTitleTextAttributes(selectedItem as [NSAttributedString.Key : Any], for: .selected)
    }
}

 override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    AppUtility.lockOrientation(.portrait)

}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    AppUtility.lockOrientation(.all)
}

}

And its extension :

extension UITabBarController {

func createNavController(vc: UIViewController, selected: UIImage, unselected: UIImage, label: String) -> UINavigationController {
    let viewController = vc
    let navController = UINavigationController(rootViewController: viewController)
    navController.tabBarItem.image = unselected
    navController.tabBarItem.selectedImage = selected
    navController.tabBarItem.title = label
    return navController
}

}

Tell me what you think about it.

1 Answer 1

2

It's so weird that selectedIndex didn't work for you, I did a similar solution and that worked for me.

Try having the correct references to your root controller ( your UITabBarController in this case ) and the child controllers, keeping them alive with a strong reference.

I have done a simple project to demonstrate it.

Programmatic TabBarController repo

I Hope I Helped!

Sign up to request clarification or add additional context in comments.

2 Comments

just quickly checked your Git repo, it looks fine ! I'll see a bit later in detail and let you know if it's ok, but the result is exactly what I need : there is no reason why I could not adapt it. I supposed the solution was about keeping strong reference with lazy var but I also thought it could be easier with simple selectedIndex, and it's definitly not... nevermind... Thanks a lot !
Nice! The lazy reference was only for convenience creation. It could be let or var, but the reference has to exist. PS. Hoping to get my first "Correct Answer" to improve my profile if it worked for you, I'm open to help further.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.