Statusbar.image has wrong color

865 views Asked by At

I am using following code for my status bar image:

let icon = NSImage(imageLiteralResourceName:"flag")
statusBarItem.image = icon

This leads to wrong color for certain background colors / modes. In the picture, what's white should be black. The image resource is white/transparent. If I change that, I get the same problem. All other status bar images will turn white on certain configurations, mine will stay black.

I was thinking that MacOS would add effects to make all statusbar icons look uniform on it's own, but apparently thats not the case...

Any ideas how to fix that?

enter image description here

Thanks!

3

There are 3 answers

1
user688262 On

I found a solution. Again I realize that MacOS development is way less supported by Apple than iOS. I think the color adjustment of statusbar icons should be the task of the operating system, but Apple lets the developer do the work. Whatever.

Here is the solution:

You have to provide two versions of your icon, one in black, the other in white.

When the app launches, you have to check wether the user's MacOs is in dark or light mode. This can be done with following code:

       let mode = UserDefaults.standard.string(forKey: "AppleInterfaceStyle")

       if (mode == "Dark"){
            let icon = NSImage(imageLiteralResourceName:"flag")
            statusBarItem.image = icon
        } else {
            let icon = NSImage(imageLiteralResourceName:"flagDark")
            statusBarItem.image = icon
        }

One problem remains here now: When the user changes the mode while your app is running, the icon color won't update. Also: If the user uses the automatic mode (i.e. it's light at day and dark in the night), the icon color won't switch as well.

You can tackle that problem by listening to a certain notification that is fired when the dark mode settings changes:

DistributedNotificationCenter.default.addObserver(self, selector: #selector(updateIcon), name: NSNotification.Name(rawValue: "AppleInterfaceThemeChangedNotification"), object: nil)

 @objc func updateIcon(){
        print("updateIcon ausgeführt")
        let mode = UserDefaults.standard.string(forKey: "AppleInterfaceStyle")
        if (mode == "Dark"){
            let icon = NSImage(imageLiteralResourceName:"flag")
            statusBarItem.image = icon
        } else {
            let icon = NSImage(imageLiteralResourceName:"flagDark")
            statusBarItem.image = icon
        }
        
        
        
    }

In my tests, this worked in all scenarios.

2
soundflix On

macOS can do what you want. I recommend reading this Apple document: https://developer.apple.com/documentation/uikit/appearance_customization/supporting_dark_mode_in_your_interface

Basically you have 2 options if you don‘t provide the code manually.

Option 1: In Xcode, navigate to your image asset in assets.xcassets. In the Attributes pane, in „Render as…“ specify „Template Image“. This worked well for my menu bar app.

Option 2: Supply different versions of your icon in one image asset, macOS will then choose the appropriate version.

0
madx On

For me this worked:

class AppDelegate: NSObject, NSApplicationDelegate {

    let statusItem = NSStatusBar.system.statusItem(withLength:NSStatusItem.squareLength)

    // ...

    func applicationDidFinishLaunching(_ aNotification: Notification) {
       // ...
       if let button = statusItem.button {
           let image = NSImage(named: NSImage.Name("TrayIcon"))
           image?.isTemplate = true
           button.image = image
        }
       // ...
    }

    // ...

}