[英]SwiftUI: Passing Data between ViewModels
Let me explain my problem/question on simple example.让我用简单的例子解释我的问题/问题。
I have first view: UserView
and realted UserViewModel
.我有第一个视图:
UserView
和 realted UserViewModel
。
I have second view: UserDetailsView
and related UserDetailsViewModel
我有第二种观点:
UserDetailsView
和相关的UserDetailsViewModel
In UserViewModel
I'm loading User
object.在
UserViewModel
,我正在加载User
object。
And then, I want pass User
object to UserDetailsViewModel
然后,我想将
User
object 传递给UserDetailsViewModel
So that UserDetailsViewModel
could manipulate with User object.这样
UserDetailsViewModel
就可以使用用户 object 进行操作。
Just to be clear, from clean code perspective, I don't want to keep User
object in my Views.需要明确的是,从简洁代码的角度来看,我不想在我的视图中保留
User
object。
View should work only with ViewModel
View 应该只适用于
ViewModel
And here is a code:这是一个代码:
struct UserView: View {
@ObservedObject var viewModel = UserViewModel()
var body: some View {
VStack {
Text(viewModel.user?.name ?? "")
if let userDetailsViewModel = viewModel.userDetailsViewModel {
NavigationLink {
UserDetailsView(viewModel: userDetailsViewModel)
} label: {
Text("See user Details")
}
}
}
}
}
class UserViewModel: ObservableObject {
@Published var user: User?
@Published var userDetailsViewModel: UserDetailsViewModel?
func fetchUser() {
APIClient.shared.loadUser { user in
self.user = user
self.userDetailsViewModel = = .init(user:
Binding(
get: {
self.user
},
set: {
self.user = $0
}
)
)
}
}
}
struct UserDetailsView: View {
@ObservedObject var viewModel: UserDetailsViewModel
var body: some View {
VStack {
Text(viewModel.user.name)
Text(viewModel.user.details)
}
}
}
class UserDetailsViewModel: ObservableObject {
@Binding var user: User
init(user: Binding<User>) {
_user = user
}
func updateUserName(_ name: String) {
APIClient.shared.updateUserName(name) { user in
self.user = user
}
}
}
I pass User
as @Binding
because I want UserView
to be updates if UserDetailsView
done some updates.我将
User
作为@Binding
传递,因为如果UserDetailsView
进行了一些更新,我希望UserView
进行更新。
And the problem is:问题是:
If in UserDetailsView
I call updateUserName()
, then UserDetailsView
is not updated.如果我在
UserDetailsView
中调用updateUserName()
,则UserDetailsView
不会更新。
Because ViewModel
is a class. And only @Published
can updated View
.因为
ViewModel
是一个 class。而且只有@Published
可以更新View
。
I know one possible solution:我知道一种可能的解决方案:
It is to add @Published var userName: String
to UserDetailsViewModel
.就是在
UserDetailsViewModel
中添加@Published var userName: String
。
And then update this property in updateUserName()
.然后在
updateUserName()
中更新此属性。
But I really feel that It's more a workaround rather then a solution.但我真的觉得它更像是一种解决方法而不是解决方案。
What if User
has many properties that I want to display in UserDetailsViewModel
?如果
User
有许多我想在UserDetailsViewModel
中显示的属性怎么办?
Then I should create @Published
property for each?那么我应该为每个创建
@Published
属性吗? Or create a separate @Published var publishedUser
?或者创建一个单独的
@Published var publishedUser
?
Can some one tell me what is the best/correct way to achieve my goal?有人能告诉我实现目标的最佳/正确方法是什么吗?
Thank you谢谢
In SwiftUI the View struct is a view model already (SwiftUI diffs the view struct data to create/update/remove actual UIViews automatically) so it is fine to store the User in @State
in the View struct, that's what its for.在 SwiftUI 中,View 结构已经是一个视图 model(SwiftUI 区分视图结构数据以自动创建/更新/删除实际的 UIView),因此可以将 User 存储在 View 结构中的
@State
中,这就是它的用途。 You can use the .task
modifier to start an async.network download, it's started when the underlying UIView
appears and cancelled when it disappears.您可以使用
.task
修饰符启动 async.network 下载,它在底层UIView
出现时启动,在它消失时取消。 It would be more work to do that using an object and you might get a leak if not done correctly.使用 object 会做更多的工作,如果操作不正确,您可能会泄漏。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.