在 SwiftUI 组件之间共享 ViewModel
Posted
技术标签:
【中文标题】在 SwiftUI 组件之间共享 ViewModel【英文标题】:Sharing ViewModel between SwiftUI components 【发布时间】:2019-12-20 11:13:43 【问题描述】:我想为使用 SwiftUI 和 Combine 实现的架构实现导航器/路由器。简而言之,View
将与Router
共享viewModel
。当View
触发viewModel
上的更改时,Router
应导航到新工作表。
这是我的代码的一个版本,我将viewModel
从View
直接传递给Router
。有什么不对的吗?我最大的疑问是,由于我在Router
和View
上都使用了@ObservedObject
,因此创建了viewModel
的两个不同实例。
查看模型
class BootViewModel:ObservableObject
@Published var presentSignIn = false
查看
struct BootView: View
@ObservedObject var viewModel:BootViewModel
var navigator:BootNavigator<BootView>? = nil
init(viewModel:BootViewModel)
self.viewModel = viewModel
self.navigator = BootNavigator(view: self, viewModel: viewModel)
self.navigator.setSubscriptions()
var body: some View
VStack
Text("Hello")
Button("Button")
self.viewModel.presentSignIn.toggle()
导航器
class BootNavigator<T:View>
var view:T? = nil
@ObservedObject var viewModel:BootViewModel
init(view:T, viewModel:BootViewModel)
self.view = view
self.viewModel = viewModel
func setSubscriptions()
subscribe(onSigninPressed: $viewModel.presentSignIn)
func subscribe(onSigninPressed : Binding<Bool>)
_ = view.sheet(isPresented: $viewModel.presentSignIn)
SignInView()
为什么从未显示SignInView
?
没有考虑到通常不需要使用带有 swiftUI 的路由器这一事实(我主要是在做一个练习)......这个实现有什么问题吗?
【问题讨论】:
【参考方案1】:这个
view.sheet(isPresented: $viewModel.presentSignIn)
SignInView()
必须位于 body
中的某个位置(直接或通过计算属性或函数)但在主体的 ViewBuilder 中
【讨论】:
你介意分享一个官方文档的链接吗?我找不到任何引用这个约束的东西【参考方案2】:我必须在这里指出一些注意事项:
值类型
UIView
和 SwiftUI View
之间存在差异。所有 SwiftUI View
s 都是值类型!因此,当您传递它们时,它们会被复制。请注意这一点。
单实例
如果您想为整个应用程序提供像常规 导航器 这样的单个实例,您可以使用单例模式。但是在 SwiftUI 世界中有一种更好的方法,称为 @Environment
对象。您可以利用这一点。
触发视图刷新
要刷新视图(包括呈现某些内容),您必须在var body
内部 编码。但可以直接通过函数等间接写入。
【讨论】:
您介意使用使用@Environment 处理导航器的代码改进答案吗?我有点困惑,因为我的每个视图都会有他们专用的导航器...... 看看this article 抱歉,您的问题需要大量基于意见的信息,而这在 SO 上是不允许的。我试图指出主题,你应该自己跟着尾巴走。但是,如果您对此有任何疑问,我的朋友,我将非常乐意提供帮助。以上是关于在 SwiftUI 组件之间共享 ViewModel的主要内容,如果未能解决你的问题,请参考以下文章
使用 100% CloudKit 和 SwiftUI 在应用程序中设置社交组件的流程?
SwiftUI中如何使用@EnvironmentObject在AppDelegate和SceneDelegate/Views之间共享数据
如何在 SwiftUI 中创建共享导航栏以在多个视图之间进行交互? [关闭]