3

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!

user688262
  • 171
  • 11
  • Does this answer your question? [NSStatusItem change image for dark tint](https://stackoverflow.com/questions/24623559/nsstatusitem-change-image-for-dark-tint) – Willeke Apr 08 '21 at 22:17

3 Answers3

3

macOS can do what you want. I recommend reading Apple documentation: 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.

soundflix
  • 928
  • 9
  • 22
  • Option 1 is spot on, thank you! – Michel Storms Mar 03 '23 at 04:35
  • Setting the image as a template is definitely the way to go. I used a "Image Set" as the image asset; I dragged my light and dark images in to the 1x and 2x spaces in the Image Set. Then I created a NSImage using the name of the Image Set - `NSImage(named: "MenubarIcon")` - and then set `.isTemplate = true` on that `NSImage`. – Peter Mar 23 '23 at 17:25
1

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
        }
       // ...
    }

    // ...

}
madx
  • 6,723
  • 4
  • 55
  • 59
0

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.

user688262
  • 171
  • 11
  • This is not the right answer. Even when the system theme is in light mode, the status bar icon will have either a black or white appearance. For example, I have black icons on my MacBook and white icons on my iMac, both in system light mode. The correct solution is as Madx said: simply use `image?.isTemplate = true` to make the system handle the icon's appearance. – Alex Mar 21 '23 at 07:20