SwiftUI中多视图共享ViewModel时视图不响应更新的问题
问题原因
你当前方案无效的核心是:RootView和SomeDeeplyNestedExampleView各自创建了完全独立的RootViewModel实例。@StateObject的作用是让每个视图拥有专属的ObservableObject实例,所以嵌套视图里调用hideFAB修改的是自己的ViewModel,根视图的ViewModel根本没收到任何变化,FAB自然不会有反应。
解决方案
推荐使用SwiftUI原生的**环境对象(EnvironmentObject)**来实现跨视图共享ViewModel,这是框架设计的标准共享数据方式,不用层层传递绑定,代码简洁且符合设计理念。
修改后的代码示例
- ViewModel保持不变:
final class RootViewModel: ObservableObject { @Published var shouldHideFAB: Bool = false func hideFAB(value: Bool) { self.shouldHideFAB = value } }
- 根视图注入ViewModel到环境:
struct RootView: View { @StateObject private var viewModel = RootViewModel() var body: some View { // 假设你用导航容器包裹子视图入口 NavigationStack { SomeDeeplyNestedExampleView() } // 将ViewModel注入到整个视图环境中 .environmentObject(viewModel) // 放置FAB .overlay( FAB() .opacity(viewModel.shouldHideFAB ? 0 : 1) ) } }
- 嵌套视图从环境获取共享ViewModel:
struct SomeDeeplyNestedExampleView: View { // 从环境中获取根视图注入的同一个ViewModel实例 @EnvironmentObject private var viewModel: RootViewModel var body: some View { Button { viewModel.hideFAB(value: true) } label: { Text("Hide the button") } } }
备选方案(不推荐但简单)
如果只是临时快速实现,也可以用单例模式,但这种方式耦合性高,不利于单元测试和后续扩展:
final class RootViewModel: ObservableObject { // 全局单例实例 static let shared = RootViewModel() // 禁止外部创建新实例 private init() {} @Published var shouldHideFAB: Bool = false func hideFAB(value: Bool) { self.shouldHideFAB = value } } // 根视图中使用 @StateObject private var viewModel = RootViewModel.shared // 嵌套视图中直接调用 Button { RootViewModel.shared.hideFAB(value: true) } label: { Text("Hide the button") }
内容的提问来源于stack exchange,提问作者darkstar
相关产品推荐
相关产品推荐

