我刚刚开始学习swift,打算构建这个数字递增的示例应用程序来理解MVVM,我不明白为什么我在视图上的数字在点击按钮时不更新。
我尝试在用户每次单击按钮时更新视图,但计数保持为零。
观点
import SwiftUI
struct ContentView: View {
@ObservedObject var viewModel = CounterViewModel()
var body: some View {
VStack {
Text("\(viewModel.model.count)")
Button(action: {
self.viewModel.increment()
}) {
Text("Increment")
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
视图模型
import SwiftUI
class CounterViewModel: ObservableObject {
@ObservedObject var model = Model()
func increment() {
self.model.count += 1
}
}
模特儿
import Foundation
class Model : ObservableObject{
@Published var count = 0
}
2条答案
按热度按时间6pp0gazn1#
以下应起作用:
请注意:ObservableObject和@Published是设计来一起工作的。只有一个值,也就是在一个被观察的对象中的值被发布,因此视图被更新。模型和视图模型之间的区别并不总是必要的,术语有点误导。你可以只把计数变量放在视图模型中。比如:
有一个自己的模型结构体(或类)是有意义的,当你从数据库或通过网络请求获取一条记录时,你的模型会获取完整的记录。
比如:
还请注意使用不可变结构体作为模型的优点(和缺点),但这是另一个主题。
iqih9akk2#
大家好,在SwiftUI中使用MVVM是一个坏主意,因为SwiftUI旨在利用快速值类型作为视图数据(如结构体),而MVVM使用慢速对象作为视图数据,这导致了SwiftUI使用值类型旨在消除的一致性错误。(以及哈佛的讲师)试图将他们的MVVM垃圾推到SwiftUI上,而不是正确地学习它。幸运的是,some of them正在改变他们的方式。
在学习SwiftUI时,我认为最好先学习值语义(对结构体的任何值更改也是对结构体本身的更改),然后是View结构体(即调用body时),然后是
@Binding
,然后是@State
。例如,尝试以下操作:然后,一旦您熟悉了视图数据,您就可以转到模型数据,这是
ObservableObject
和singletons开始发挥作用的时候,例如。注意,我们使用单例是因为使用
@StateObject
作为模型数据是危险的,因为它的生存期与屏幕上的某些东西相关联,我们可能会意外地丢失所有的模型数据,这些数据的生存期应该与应用程序的运行相关联。当您需要@State
中的引用类型时,最好考虑@StateObject
,即涉及视图数据。当涉及到异步网络时,使用新的
.task
修饰符可以避免@StateObject
。