You need to enable JavaScript to run this app. SwiftUI macOS AppDelegate如何监听ObservedObject属性状态变化
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI macOS AppDelegate如何监听ObservedObject属性状态变化

实现方案

核心问题说明

你现有的实现存在两个不生效的问题:

  • @ObservedObject 是SwiftUI专属属性包装器,仅能在SwiftUI View中使用,在AppDelegate(NSObject子类)中无法触发监听回调
  • @Environment(\.colorScheme) 同样是SwiftUI专属属性,在AppDelegate中无法获取到正确的系统外观值

具体修改逻辑

使用Combine框架监听UserPreferences中@Published修饰的属性变化即可实现需求:

  1. 导入Combine框架
  2. 在AppDelegate中声明存储订阅的AnyCancellable集合
  3. 在applicationDidFinishLaunching中添加对backgroundIsTransparent属性的订阅,状态变化时触发对应更新逻辑
  4. 修正系统外观的获取方式,改用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.08 13:24:03