如何使用 Swift 检测 macOS 默认模式和暗模式之间的切换 3
How to detect switch between macOS default & dark mode using Swift 3
我想在用户从默认模式切换到深色模式时更改我的状态栏应用程序图标,反之亦然(使用 Swift 3)。这是我目前所拥有的:
func applicationDidFinishLaunching(_ aNotification: Notification) {
DistributedNotificationCenter.default().addObserver(self, selector: #selector(darkModeChanged(sender:)), name: "AppleInterfaceThemeChangedNotification", object: nil)
}
...
func darkModeChanged(sender: NSNotification) {
print("mode changed")
}
不幸的是,它不起作用。我做错了什么?
我成功地使用了 Swift 3 语法:
DistributedNotificationCenter.default.addObserver(self, selector: #selector(interfaceModeChanged(sender:)), name: NSNotification.Name(rawValue: "AppleInterfaceThemeChangedNotification"), object: nil)
func interfaceModeChanged(sender: NSNotification) {
...
}
Swift 5, Xcode 10.2.1, macOS 10.14.4
很棒的东西。我对@Jeffrey 的回答的两分钱:
extension Notification.Name {
static let AppleInterfaceThemeChangedNotification = Notification.Name("AppleInterfaceThemeChangedNotification")
}
所以可以(而不是 rawValue
):
func listenToInterfaceChangesNotification() {
DistributedNotificationCenter.default.addObserver(
self,
selector: #selector(interfaceModeChanged),
name: .AppleInterfaceThemeChangedNotification,
object: nil
)
}
记住@objc
属性:
@objc func interfaceModeChanged() {
// Do stuff.
}
如果您只需要为深色模式更新图标图像,您可以通过创建自动更新的动态图像在没有通知的情况下执行此操作。
来自 Apple 的 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.
所以,我的小补充:
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
}
}
在 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)
}
其中 setAppearance
对风格的变化做出反应。
我想在用户从默认模式切换到深色模式时更改我的状态栏应用程序图标,反之亦然(使用 Swift 3)。这是我目前所拥有的:
func applicationDidFinishLaunching(_ aNotification: Notification) {
DistributedNotificationCenter.default().addObserver(self, selector: #selector(darkModeChanged(sender:)), name: "AppleInterfaceThemeChangedNotification", object: nil)
}
...
func darkModeChanged(sender: NSNotification) {
print("mode changed")
}
不幸的是,它不起作用。我做错了什么?
我成功地使用了 Swift 3 语法:
DistributedNotificationCenter.default.addObserver(self, selector: #selector(interfaceModeChanged(sender:)), name: NSNotification.Name(rawValue: "AppleInterfaceThemeChangedNotification"), object: nil)
func interfaceModeChanged(sender: NSNotification) {
...
}
Swift 5, Xcode 10.2.1, macOS 10.14.4
很棒的东西。我对@Jeffrey 的回答的两分钱:
extension Notification.Name {
static let AppleInterfaceThemeChangedNotification = Notification.Name("AppleInterfaceThemeChangedNotification")
}
所以可以(而不是 rawValue
):
func listenToInterfaceChangesNotification() {
DistributedNotificationCenter.default.addObserver(
self,
selector: #selector(interfaceModeChanged),
name: .AppleInterfaceThemeChangedNotification,
object: nil
)
}
记住@objc
属性:
@objc func interfaceModeChanged() {
// Do stuff.
}
如果您只需要为深色模式更新图标图像,您可以通过创建自动更新的动态图像在没有通知的情况下执行此操作。
来自 Apple 的 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.
所以,我的小补充:
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
}
}
在 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)
}
其中 setAppearance
对风格的变化做出反应。