13

I want to change my status bar app icon when the user switches from default to dark mode and vice versa (using Swift 3). Here’s what i have so far:

func applicationDidFinishLaunching(_ aNotification: Notification) { DistributedNotificationCenter.default().addObserver(self, selector: #selector(darkModeChanged(sender:)), name: "AppleInterfaceThemeChangedNotification", object: nil) } ... func darkModeChanged(sender: NSNotification) { print("mode changed") } 

Unfortunately, it’s not working. What am I doing wrong?

4 Answers 4

19

I'm using this Swift 3 syntax successfully:

DistributedNotificationCenter.default.addObserver(self, selector: #selector(interfaceModeChanged(sender:)), name: NSNotification.Name(rawValue: "AppleInterfaceThemeChangedNotification"), object: nil) func interfaceModeChanged(sender: NSNotification) { ... } 
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you so much, great solution! :)
it's not working in Mac catalyst. is there any way to achieve this in Mac catalyst?
i need objective-c syntax.
3

Swift 5, Xcode 10.2.1, macOS 10.14.4

Great stuff. My two cents around @Jeffrey's answer:

extension Notification.Name { static let AppleInterfaceThemeChangedNotification = Notification.Name("AppleInterfaceThemeChangedNotification") } 

So one could (instead of rawValue):

func listenToInterfaceChangesNotification() { DistributedNotificationCenter.default.addObserver( self, selector: #selector(interfaceModeChanged), name: .AppleInterfaceThemeChangedNotification, object: nil ) } 

Remember the @objc attribute:

@objc func interfaceModeChanged() { // Do stuff. } 

Comments

1

So, my little additions as well:

enum InterfaceStyle: String { case Light case Dark case Unspecified } extension Notification.Name { static let AppleInterfaceThemeChangedNotification = Notification.Name("AppleInterfaceThemeChangedNotification") } extension NSViewController { var interfaceStyle: InterfaceStyle { let type = UserDefaults.standard.string(forKey: "AppleInterfaceStyle") ?? "Unspecified" return InterfaceStyle(rawValue: type) ?? InterfaceStyle.Unspecified } } 

and somewhere in a NSViewController:

 DistributedNotificationCenter.default.addObserver(forName: .AppleInterfaceThemeChangedNotification, object: nil, queue: OperationQueue.main) { [weak weakSelf = self] (notification) in // add an observer for a change in interface style weakSelf?.setAppearance(toStyle: weakSelf!.interfaceStyle) } 

where setAppearance reacts on the change of style.

Comments

0

If you simply need to update icon images for dark mode, you can do this without notifications by creating a dynamic image that updates automatically.

From Apple's documentation:

To create an image that draws its content dynamically, use the init(size:flipped:drawingHandler:) method to initialize your image with a custom drawing handler block. AppKit calls your handler block whenever the system appearance changes, giving you a chance to redraw the image using the new appearance.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.