0
votes

First of all, I'm a newbie to Swift so apologies if I'm missing something obvious or using the wrong terminology.

Objective: set tab bar item selected image to custom image.

The following setup works (selected item is custom image):

| UITabBarController | => | UIViewController | (setup w/ storyboard)

class MyViewController: UIViewController {  
    override func viewDidLoad() {
        super.viewDidLoad()
        let customSelectedImage = UIImage (named: "selected-image")?.withRenderingMode(.alwaysOriginal)
        self.tabBarItem.selectedImage = customSelectedImage
    }
}

But this setup doesn't work (selected item has default blue tint):

| UITabBarController | => | UINavigationController | => | UIViewController | (setup w/ storyboard - see here)

Similar code to above but added (programmatically) UICollectionView subview to UIViewController.

class MyViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {  
    override func viewDidLoad() {
        super.viewDidLoad()
        let customSelectedImage = UIImage (named: "selected-image")?.withRenderingMode(.alwaysOriginal)
        self.tabBarItem.selectedImage = customSelectedImage
        ...
        //Some UICollectionView related code
        ...
    }
}

Some things that may be helpful:

  • In debug session (see print screen) => View UI hierarchy: the selected item (marked as of class UITabBarSwappableImageView) has the correct custom image but the tint is default blue. I tried with different custom images and looks as if they're hidden by another (default ?) view...
  • If I change the UITabBar.appearance().tintColor = UIColor.red in AppDelegate.swift application(... didFinishLaunchingWithOptions ...) function then the selected item has a red (vs blue) tint.

What's happening?

1

1 Answers

0
votes

I extend UITabBarController:

extension UITabBarController {

    func updateTabBarItem(tab: Int, image: UIImage?) {

        guard let tabItems = tabBar.items, tab < tabItems.count && tab >= 0
            else { return }

        let tabItem = tabItems[tab]
        tabItem.image = image?.withRenderingMode(.alwaysOriginal)
        tabItem.selectedImage = tabItem.image

    }

}

This will help to access the tabBar.items without loading any view controllers (except the first view controller of the tab 0).

class MyViewController: UIViewController {

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        tabBarController?.updateTabBarItem(tab: 1, image: UIImage(named: "selected-image")) // update the second tab's image here (just for example)
    }

}

For example, if you want to change the tab 2 selected image, make a break point on viewDidLoad: on the second view controller, you will find the break point doesn't hit, that's why the tab item's image wouldn't be updated.