我想根据MVVM从视图模型中分离视图。我如何在SwiftUI中创建模型?我读到应该使用结构而不是类。
作为一个例子,我有一个公园的模型,你可以种树:
// View Model
struct Park {
var numberOfTrees = 0
func plantTree() {
numberOfTrees += 1 // Cannot assign to property: 'self' is immutable
}
}
// View
struct ParkView: View {
var park: Park
var body: some View {
// …
}
}
在这样的东西中阅读关于@State
的东西,这使得结构体有些可变,所以我尝试:
struct Park {
@State var numberOfTrees = 0 // Enum 'State' cannot be used as an attribute
func plantTree() {
numberOfTrees += 1 // Cannot assign to property: 'self' is immutable
}
}
我确实在View
中成功地直接使用了@State
,但这对分离视图模型代码没有帮助。
我可以使用class
:
class Park: ObservableObject {
var numberOfTrees = 0
func plantTree() {
numberOfTrees += 1
}
}
...但是我在使用嵌套在另一个视图模型中的视图模型时会遇到麻烦,比如City
:
struct City {
@ObservedObject var centerPark: Park
}
centerPark
中的更改不会发布为Park
现在是引用类型(至少在我的测试或here中不会)。另外,我想知道您如何使用struct
解决此问题。
2条答案
按热度按时间klr1opcd1#
作为一个起点:
umuewwlo2#
mutating func
是修复,但我想我会包括一些其他信息如下:我们不将MVVM与SwiftUI一起使用,因为我们不将类用于 transient 视图状态,并且我们不从MVVM/MVC的Angular 控制视图。SwiftUI自动为我们创建和更新真实的视图对象,即UILabels、UITableView等。SwiftUI
View
结构本质上已经是视图模型,因此,如果您要将其重新创建为对象,不仅会不必要地使代码更加复杂,而且还会引入对象引用错误,SwiftUI正试图通过使用结构来消除这些错误。使用@State
和@Binding
这样的属性 Package 器,SwiftUI正在发挥一些魔力,使结构体的行为像一个对象,忽略这一点并不是一个好主意。要使视图结构体更具可测试性,可以将相关的变量提取到结构体中,并使用如下所示的变异函数:你可以看到苹果在4:18的Data Essentials in SwiftUI WWDC 2020中演示了这种模式,他说:“EditorConfig可以维护其属性的不变量,并且可以独立测试。由于EditorConfig是一种值类型,因此对EditorConfig属性的任何更改(如其进度)都可以作为对EditorConfig本身的更改看到。”