我觉得这是一个已经在某个地方被问到的问题,但我找不到太多关于它的信息。
当使用变量来更新UI时,我们何时/为什么要在视图中使用@State
,而不是在ViewModel中使用@Published
?
这是在我试图掌握MVVM体系结构的背景下。我一般理解其中的区别,只是不是当涉及到两者都可以用同样的方式轻松完成的事情时。
下面,我有两个例子做同样的事情,但是一个使用@State
,而另一个使用@Published
和一个ViewModel。@State
示例:
struct MyView: View {
@State var backgroundIsRed = false
var body: some View {
ZStack {
if backgroundIsRed {
Color.red
} else {
Color.green
}
}
.onTapGesture { backgroundIsRed.toggle() }
}
}
@Published
示例:
class ViewModel: ObservableObject {
@Published var backgroundIsRed = false
}
struct MyView: View {
@StateObject var viewModel = ViewModel()
var body: some View {
ZStack {
if viewModel.backgroundIsRed {
Color.red
} else {
Color.green
}
}
.onTapGesture { viewModel.backgroundIsRed.toggle() }
}
}
2条答案
按热度按时间4uqofj5v1#
例如,我认为“Published”方法可以帮助您为VM创建测试结构。
以您的示例为例,您可以创建一个协议:
然后道:
另一方面,State方法提供了一种实现逻辑的更直接的方法。
除此之外,没有任何特别的理由认为一个比另一个更好。希望这能帮助你选择在每种情况下应该使用哪一个。
s2j5cfk02#
我们在SwiftUI中不需要MVVM,因为
View
结构体已经是视图模型了,也就是说,它保存了SwiftUI用来创建/更新/删除屏幕上实际UIView
对象的数据。如果使用实际对象来完成这项工作,那么你就添加了不必要的间接层,并且会得到SwiftUI巧妙使用值语义所要消除的那种一致性错误。最好把
@StateObject
看作@State
,但如果你需要一个引用类型,比如你想异步加载/保存/同步数据。现在我们有了功能更强大的.task
修饰符,这种情况并不常见。如果你的目标是将相关的变量组合在一起,并拥有可测试的逻辑,那么只需使用带有自定义结构体的
@State var
,这比正确实现@StateObject
要简单得多。然而,你必须首先学习用于你的逻辑的mutating func
。同样,如果你想在自定义结构体中访问@Environment
,你需要学习DynamicProperty
。