SwiftUI macOs AppDelegate 检测 ObservedObject 的变化
SwiftUI macOs AppDelegate detect the change of ObservedObject
我有下面的AppDelegate
class,我想确定userPreferences.backgroundIsTransparent
什么时候改变状态,必须调用AppDelegate
里面的一个函数。
我看了这里:
但我没弄清楚如何在我的案例中使用它。
我该怎么办?
AppDelegate:
import Cocoa
import SwiftUI
@main
class AppDelegate: NSObject, NSApplicationDelegate {
var popover = NSPopover.init()
var statusBar: StatusBarController?
@Environment(\.colorScheme) var colorScheme
@ObservedObject var userPreferences = UserPreferences.instance
func applicationDidFinishLaunching(_ aNotification: Notification) {
let contentView = ContentView()
popover.contentSize = NSSize(width: 560, height: 360)
popover.contentViewController = NSHostingController(rootView: contentView)
statusBar = StatusBarController.init(popover)
DistributedNotificationCenter.default.addObserver(self, selector: #selector(interfaceModeChanged(sender:)), name: NSNotification.Name(rawValue: "AppleInterfaceThemeChangedNotification"), object: nil)
}
func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
}
@objc func interfaceModeChanged(sender: NSNotification) {
//popover.backgroundColor = colorScheme == .dark ? #colorLiteral(red: 0.3411764801, green: 0.6235294342, blue: 0.1686274558, alpha: 1) : #colorLiteral(red: 0.2392156869, green: 0.6745098233, blue: 0.9686274529, alpha: 1)
popover.backgroundColor = NSColor(named: "backgroundTheme")?.withAlphaComponent(userPreferences.backgroundIsTransparent ? 0.3 : 1.0)
print("change", colorScheme)
}
}
import EventKit
import ServiceManagement
private struct PreferencesKeys {
static let backgroundIsTransparent = "backgroundIsTransparent"
static let isDarkMode = "isDarkMode"
}
class UserPreferences: ObservableObject {
static let instance = UserPreferences()
private init() {
// This prevents others from using the default '()' initializer for this class.
}
private static let defaults = UserDefaults.standard
@Published var backgroundIsTransparent: Bool = {
guard UserDefaults.standard.object(forKey: PreferencesKeys.backgroundIsTransparent) != nil else {
return true
}
return UserDefaults.standard.bool(forKey: PreferencesKeys.backgroundIsTransparent)
}() {
didSet {
UserPreferences.defaults.set(backgroundIsTransparent, forKey: PreferencesKeys.backgroundIsTransparent)
}
}
@Published var isDarkMode: Bool = {
guard UserDefaults.standard.object(forKey: PreferencesKeys.isDarkMode) != nil else {
return true
}
return UserDefaults.standard.bool(forKey: PreferencesKeys.isDarkMode)
}() {
didSet {
UserPreferences.defaults.set(isDarkMode, forKey: PreferencesKeys.isDarkMode)
}
}
}
有一种更复杂的观察方式UserDefaults
。
Combine
框架为UserDefaults
提供了一个publisher,其实就是一个Key-Value Observing Publisher
首先让你的 backgroundIsTransparent
属性 成为 UserDefaults
的扩展
extension UserDefaults {
@objc var backgroundIsTransparent: Bool {
get {
guard object(forKey: PreferencesKeys.backgroundIsTransparent) != nil else { return true }
return bool(forKey: PreferencesKeys.backgroundIsTransparent)
}
set {
set(newValue, forKey: PreferencesKeys.backgroundIsTransparent)
}
}
}
在 AppDelegate 中导入 Combine
并为订阅创建一个 Set
import Combine
@main
class AppDelegate: NSObject, NSApplicationDelegate { ...
private var subscriptions = Set<AnyCancellable>()
并在 applicationDidFinishLaunching
中添加发布者
func applicationDidFinishLaunching(_ aNotification: Notification) {
// .....
UserDefaults.standard.publisher(for: \.backgroundIsTransparent)
.sink { state in
print(state)
// do something with state
}
.store(in: &subscriptions)
}
使用您的方法的另一种方法是使 userPreferences
成为 @StateObject
@StateObject var userPreferences = UserPreferences.instance
并观察 backgroundIsTransparent
userPreferences.$backgroundIsTransparent
.sink { state in
print(state)
// do something with state
}
.store(in: &subscriptions)
我有下面的AppDelegate
class,我想确定userPreferences.backgroundIsTransparent
什么时候改变状态,必须调用AppDelegate
里面的一个函数。
我看了这里:
但我没弄清楚如何在我的案例中使用它。
我该怎么办?
AppDelegate:
import Cocoa
import SwiftUI
@main
class AppDelegate: NSObject, NSApplicationDelegate {
var popover = NSPopover.init()
var statusBar: StatusBarController?
@Environment(\.colorScheme) var colorScheme
@ObservedObject var userPreferences = UserPreferences.instance
func applicationDidFinishLaunching(_ aNotification: Notification) {
let contentView = ContentView()
popover.contentSize = NSSize(width: 560, height: 360)
popover.contentViewController = NSHostingController(rootView: contentView)
statusBar = StatusBarController.init(popover)
DistributedNotificationCenter.default.addObserver(self, selector: #selector(interfaceModeChanged(sender:)), name: NSNotification.Name(rawValue: "AppleInterfaceThemeChangedNotification"), object: nil)
}
func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
}
@objc func interfaceModeChanged(sender: NSNotification) {
//popover.backgroundColor = colorScheme == .dark ? #colorLiteral(red: 0.3411764801, green: 0.6235294342, blue: 0.1686274558, alpha: 1) : #colorLiteral(red: 0.2392156869, green: 0.6745098233, blue: 0.9686274529, alpha: 1)
popover.backgroundColor = NSColor(named: "backgroundTheme")?.withAlphaComponent(userPreferences.backgroundIsTransparent ? 0.3 : 1.0)
print("change", colorScheme)
}
}
import EventKit
import ServiceManagement
private struct PreferencesKeys {
static let backgroundIsTransparent = "backgroundIsTransparent"
static let isDarkMode = "isDarkMode"
}
class UserPreferences: ObservableObject {
static let instance = UserPreferences()
private init() {
// This prevents others from using the default '()' initializer for this class.
}
private static let defaults = UserDefaults.standard
@Published var backgroundIsTransparent: Bool = {
guard UserDefaults.standard.object(forKey: PreferencesKeys.backgroundIsTransparent) != nil else {
return true
}
return UserDefaults.standard.bool(forKey: PreferencesKeys.backgroundIsTransparent)
}() {
didSet {
UserPreferences.defaults.set(backgroundIsTransparent, forKey: PreferencesKeys.backgroundIsTransparent)
}
}
@Published var isDarkMode: Bool = {
guard UserDefaults.standard.object(forKey: PreferencesKeys.isDarkMode) != nil else {
return true
}
return UserDefaults.standard.bool(forKey: PreferencesKeys.isDarkMode)
}() {
didSet {
UserPreferences.defaults.set(isDarkMode, forKey: PreferencesKeys.isDarkMode)
}
}
}
有一种更复杂的观察方式UserDefaults
。
Combine
框架为UserDefaults
提供了一个publisher,其实就是一个Key-Value Observing Publisher
首先让你的 backgroundIsTransparent
属性 成为 UserDefaults
extension UserDefaults {
@objc var backgroundIsTransparent: Bool {
get {
guard object(forKey: PreferencesKeys.backgroundIsTransparent) != nil else { return true }
return bool(forKey: PreferencesKeys.backgroundIsTransparent)
}
set {
set(newValue, forKey: PreferencesKeys.backgroundIsTransparent)
}
}
}
在 AppDelegate 中导入 Combine
并为订阅创建一个 Set
import Combine
@main
class AppDelegate: NSObject, NSApplicationDelegate { ...
private var subscriptions = Set<AnyCancellable>()
并在 applicationDidFinishLaunching
中添加发布者
func applicationDidFinishLaunching(_ aNotification: Notification) {
// .....
UserDefaults.standard.publisher(for: \.backgroundIsTransparent)
.sink { state in
print(state)
// do something with state
}
.store(in: &subscriptions)
}
使用您的方法的另一种方法是使 userPreferences
成为 @StateObject
@StateObject var userPreferences = UserPreferences.instance
并观察 backgroundIsTransparent
userPreferences.$backgroundIsTransparent
.sink { state in
print(state)
// do something with state
}
.store(in: &subscriptions)