Search code examples
iosswiftxcodeuitabbaruitabbaritem

iOS Simulator shows white background on transparent images with template rendering mode


The icons in my tab bar are showing white backgrounds behind them even though the image set in the Asset catalog has "Render As" set to "Template Image". Here are some cases:

No background set at all on the UITabBar

With no background setting

Same image darkened and contrast changed to bring out the background behind the icon

With no background setting, image enhanced

Same image but using a red background set with UITabBar.appearance().barTintColor = red

enter image description here

Here's a newly exported shape from Sketch's iOS UI library, exported with iOS settings and with all 3 sizes:

With a green background

The final PNG that I use

The final png

The PNG as viewed from Pixelmator, showing transparency

A screenshot of the icon in Pixelmator

The images are set to template mode in the asset catalog and programmatically. Each background set with UITabBars appearance() and I'm not subclassing UITabBarController, and I'm not using storyboards, and here is all the code I have to reproduce this issue with var names simplified:

// AppDelegate
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    window = UIWindow(frame: UIScreen.main.bounds)
    let tabBarController = UITabBarController()
    // let controllers = [...]
    tabBarController.setViewControllers(controllers, animated: false)
    UITabBar.appearance().tintColor = UIColor.brown
    UITabBar.appearance().barTintColor = // red, green, etc
    window!.rootViewController = tabBarController
    window!.makeKeyAndVisible()
    return true
}

And here is where I set the UITabBarItem in that controller:

// The controller with the tab icon
override init(style: UITableViewStyle) {
    super.init(style: style)        
    let booImage = UIImage(named: "boo")?.withRenderingMode(.alwaysTemplate)
    self.tabBarItem = UITabBarItem(title: "Controller", image: booImage, tag: 1)
}

Aside from these few lines of code, this is a fresh project with no other changes. It seems to see that the image is a template because I'm able to tint the shape any color I want, but that white background always remains.

Based on documentation, there are no other steps required to use a templated image as a UITabBarItem icon. Anyone have an idea why the white background shows up on the UITabBarItems? Does it have anything to do with the fact that its running in the simulator?


Solution

  • Can't reproduce. Here's my app running in the 5s simulator (in landscape); there's no "white background":

    enter image description here

    Here's the entirety of the code:

    // AppDelegate.swift
    
    import UIKit
    @UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate {
        var window: UIWindow?
        func application(_ application: UIApplication, didFinishLaunchingWithOptions
            launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
                self.window = self.window ?? UIWindow()
                let tabBarController = UITabBarController()
                let controllers = [ViewController()]
                tabBarController.setViewControllers(controllers, animated: false)
                UITabBar.appearance().tintColor = .yellow
                UITabBar.appearance().barTintColor = .red
                self.window!.rootViewController = tabBarController
                self.window!.makeKeyAndVisible()
                return true
        }
    }
    
    // ViewController.swift
    
    import UIKit
    class ViewController: UIViewController {
        init() {
            super.init(nibName: nil, bundle: nil)
            let booImage = UIImage(named: "ghost")?.withRenderingMode(.alwaysTemplate)
            self.tabBarItem = UITabBarItem(title: "Controller", image: booImage, tag: 1)
            self.view.backgroundColor = .white
        }
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    }