SwiftUI跨iOS/macOS应用如何将@StateObject传递给AppDelegate内的视图
解决方案
你遇到的是SwiftUI层对象与AppKit层Delegate对象的属性互通问题,可通过以下两种方式解决:
方案一:通过App层向Delegate传递实例(保留原有代码结构)
步骤1:给AppDelegate增加Config存储属性
class AppDelegate: NSObject, NSApplicationDelegate { // 新增可接收Config实例的属性 var configuration: Config? { didSet { guard let configuration = configuration else { return } // 将原有创建popover的逻辑挪到此处,此时已拿到完整的Config实例 let macSampleView = MacSampleView() .environmentObject(configuration) let popover = NSPopover() // 剩余原有逻辑:创建状态栏项、配置popover属性等 popover.contentViewController = NSHostingController(rootView: macSampleView) } } func applicationDidFinishLaunching(_ aNotification: Notification) { // 此处保留不需要Config实例的初始化逻辑即可,例如隐藏Dock图标 NSApp.setActivationPolicy(.accessory) } }
步骤2:在App层将Config实例注入到AppDelegate
修改SampleApp的Scene代码,通过onAppear修饰符完成注入:
@main struct SampleApp: App { @StateObject var configuration = Config() #if os(macOS) @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate #endif var body: some Scene { #if os(macOS) Settings { EmptyView() } // 新增注入逻辑 .onAppear { appDelegate.configuration = configuration } #else WindowGroup { SampleView().environmentObject(configuration) } #endif } }
方案二:使用全局单例管理配置(更适合全局配置类场景)
如果你的Config类本身就是全局唯一的配置实例,直接做成单例可省去传递逻辑:
步骤1:修改Config类为单例
class Config: ObservableObject { // 全局唯一实例 static let shared = Config() // 你的原有属性和逻辑 // 私有构造方法,禁止外部创建新实例 private init() {} }
步骤2:全局直接调用单例
- SampleApp中使用单例初始化
@StateObject:
@StateObject var configuration = Config.shared
- AppDelegate中直接使用单例给视图注入:
let macSampleView = MacSampleView() .environmentObject(Config.shared)
内容的提问来源于stack exchange,提问作者s303
相关产品推荐
相关产品推荐

