[英]Sharing ViewModel between SwiftUI components
I'd like to implement a navigator/router for an architecture implemented with SwiftUI and Combine.我想为使用 SwiftUI 和 Combine 实现的架构实现导航器/路由器。 In a few words the View
will share viewModel
with Router
.简而言之, View
将与Router
共享viewModel
。 When the View
triggers a change on the viewModel
the Router
should navigate to a new sheet.当View
触发的改变viewModel
的Router
应该导航到新的工作表。
This is a version of my code where I'm directly passing the viewModel
from View
to Router
.这是我的代码的一个版本,我直接将viewModel
从View
传递到Router
。 Is there anything wrong?有什么不对的吗? My biggest doubt is that since I'm using @ObservedObject
on both the Router
and the View
, two different instances of the viewModel
are created.我最大的疑问是,由于我在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
is never presented?为什么SignInView
永远不会出现?This这个
view.sheet(isPresented: $viewModel.presentSignIn){
SignInView()
MUST be somewhere in body
(directly or via computed property or func) but inside body's ViewBuilder必须在body
某个地方(直接或通过计算属性或 func)但在 body 的 ViewBuilder 内
Some notes I have to point out here:我必须在这里指出的一些注意事项:
There is a difference between an UIView
and a SwiftUI View
. UIView
和 SwiftUI View
之间存在差异。 All SwiftUI View
s are value type!所有 SwiftUI View
都是值类型! So they get copied when you pass them around.因此,当您传递它们时,它们会被复制。 Be aware of that.请注意这一点。
If you want a single instance like a regular navigator for your entire app, you can use singleton pattern.如果你想要一个单一的实例,比如整个应用程序的常规导航器,你可以使用单例模式。 But there is a better approach in SwiftUI universe called @Environment
objects.但是 SwiftUI 宇宙中有一种更好的方法,称为@Environment
对象。 You can take advantage of that.你可以利用这一点。
To refresh the view (including presenting something), you must code inside the var body
.要刷新视图(包括呈现某些内容),您必须在var body
内编码。 But it can be directly written on indirectly through a function or etc.但它可以通过函数等间接写入。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.