如何在SwiftUI的macOS多窗口(WindowGroup)中避免状态共享
SwiftUI多窗口场景:区分全局共享状态与窗口本地状态
我正在开发适配iOS/iPadOS/macOS的跨平台应用,需要在macOS上支持多窗口功能。通过WindowGroup已经实现了原生多窗口,也能通过状态栏打开新窗口,但目前无法正确区分全局共享状态和窗口本地状态。
我的需求是:打开新窗口时,Api对象在所有窗口间共享,NavManager对象则为每个窗口维护独立的状态。
以下是简化的应用入口代码:
import SwiftUI @Observable class NavManager { enum NavItem { case a case b } var currentNav: NavItem = .a } @Observable class Api { var someProperty: String = "Hello World" } struct NavigationView: View { @State private var navManager: NavManager = NavManager() var body: some View { switch navManager.currentNav { case .a: Text("Navigated to a") case .b: Text("Navigated to b") } Button { if navManager.currentNav == .a { navManager.currentNav = .b } else { navManager.currentNav = .a } } label: { Text("Toggle navigation") } Text("Some subview hierarchy that needs navManager") .environment(navManager) } } @main struct MPFApp: App { @State private var api: Api = Api() var body: some Scene { WindowGroup { NavigationView() .environment(api) } } }
但当前代码存在问题:navManager的状态在多窗口间是共享的,切换一个窗口的导航状态时,其他窗口的导航状态会同步变化,不符合每个窗口独立维护导航状态的预期。我在Apple官网及WWDC演讲中未找到明确的说明。
更新:问题已解决
该功能现已正常工作,核心注意点是:不要在App视图中初始化NavManager,必须在NavigationView内部用@State初始化。
原理说明:WindowGroup每次创建新窗口时,会重新实例化其内部的整个视图层级。将NavManager的@State声明放在NavigationView内部,每个新窗口都会生成一个独立的NavManager实例,从而实现窗口本地状态的隔离;而Api在App层级用@State声明,会被所有窗口共享,保证全局状态的一致性。
内容的提问来源于stack exchange,提问作者thiezn
相关产品推荐
相关产品推荐

