SwiftUI macOS AppDelegate如何监听ObservedObject属性状态变化
实现方案
核心问题说明
你现有的实现存在两个不生效的问题:
@ObservedObject是SwiftUI专属属性包装器,仅能在SwiftUI View中使用,在AppDelegate(NSObject子类)中无法触发监听回调@Environment(\.colorScheme)同样是SwiftUI专属属性,在AppDelegate中无法获取到正确的系统外观值
具体修改逻辑
使用Combine框架监听UserPreferences中@Published修饰的属性变化即可实现需求:
- 导入Combine框架
- 在AppDelegate中声明存储订阅的
AnyCancellable集合 - 在
applicationDidFinishLaunching中添加对backgroundIsTransparent属性的订阅,状态变化时触发对应更新逻辑 - 修正系统外观的获取方式,改用AppKit原生的API获取
修改后完整代码
AppDelegate.swift
import Cocoa import SwiftUI import Combine // 新增导入Combine @main class AppDelegate: NSObject, NSApplicationDelegate { var popover = NSPopover.init() var statusBar: StatusBarController? // 移除无效的@Environment属性,改用AppKit原生API获取外观 // 移除@ObservedObject,直接持有单例 var userPreferences = UserPreferences.instance // 新增存储订阅的集合 private var cancellables = Set<AnyCancellable>() 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(updatePopoverBackground), name: NSNotification.Name(rawValue: "AppleInterfaceThemeChangedNotification"), object: nil) // 新增监听backgroundIsTransparent状态变化 userPreferences.$backgroundIsTransparent .receive(on: DispatchQueue.main) // 确保UI更新在主线程执行 .sink { [weak self] _ in self?.updatePopoverBackground() } .store(in: &cancellables) // 初始化时调用一次设置初始背景 updatePopoverBackground() } func applicationWillTerminate(_ aNotification: Notification) { // 清理通知订阅 DistributedNotificationCenter.default.removeObserver(self) } // 将原interfaceModeChanged方法重命名为通用的更新背景方法 @objc func updatePopoverBackground() { // 用AppKit原生API判断当前是否为深色模式 let isDarkMode = NSApp.effectiveAppearance.bestMatch(from: [.darkAqua, .aqua]) == .darkAqua popover.backgroundColor = NSColor(named: "backgroundTheme")?.withAlphaComponent(userPreferences.backgroundIsTransparent ? 0.3 : 1.0) print("change", isDarkMode) } }
UserPreferences.swift
无需修改,现有代码已经满足需求。
内容的提问来源于stack exchange,提问作者Paul
相关产品推荐
相关产品推荐

