我想根據 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
}
}
我確實@State直接在View. 不過,這無助于分離視圖模型代碼。
我可以使用class:
class Park: ObservableObject {
var numberOfTrees = 0
func plantTree() {
numberOfTrees = 1
}
}
…但是我會在使用嵌套在另一個視圖模型中的這個視圖模型時遇到問題,比如City:
struct City {
@ObservedObject var centerPark: Park
}
centerPark不會發布更改,因為Park現在是參考型別(至少不在我的測驗中或此處)。另外,我想知道您如何使用struct.
uj5u.com熱心網友回復:
作為起點:
// Model
struct Park {
var numberOfTrees = 0
mutating func plantTree() { // `mutating`gets rid of your error
numberOfTrees = 1
}
}
// View Model
class CityVM: ObservableObject {
@Published var park = Park() // creates a Park and publishes it to the views
// ... other @Published things ...
// Intents:
func plantTree() {
park.plantTree()
}
}
// View
struct ParkView: View {
// create the ViewModel, which creates the model(s)
// usually you would do this in the App struct and make available to all views by .environmentObject
@StateObject var city = CityVM()
var body: some View {
VStack {
Text("My city has \(city.park.numberOfTrees) trees.")
Button("Plant one more") {
city.plantTree()
}
}
}
}
uj5u.com熱心網友回復:
mutating func是修復,但我想我會在下面包含一些其他資訊:
我們不將 MVVM 與 SwiftUI 一起使用,因為我們不將類用于瞬態視圖狀態,并且我們不控制 MVVM/MVC 意義上的視圖。SwiftUI 會自動為我們創建和更新螢屏上的視圖,即 UILabel、UITableView 等。SwiftUI 視圖結構本質上已經是視圖模型,因此,如果您將其重新創建為物件,不僅會使您的代碼變得不必要地復雜,而且還會引入 SwiftUI 試圖通過使用結構來消除的物件參考錯誤。使用像這樣的屬性包裝器@State和@BindingSwiftUI 正在做一些魔術來使結構表現得像一個物件,忽略它不是一個好主意。為了使您的 View 結構更具可測驗性,您可以將相關的變數提取到結構中并使用如下的變異函式:
// View Model
struct ParkConfig {
var numberOfTrees = 0
mutating func plantTree() {
numberOfTrees = 1
}
}
struct ContentView {
@State var parkConfig = ParkConfig()
var body: some View {
ParkView(config: $parkConfig)
}
}
// View
struct ParkView: View {
@Binding var config: ParkConfig
var body: some View {
Button("Click Me") {
config.plantTree()
}
}
}
您可以看到 Apple在 SwiftUI WWDC 2020 的 Data Essentials 中的 4:18 演示了這種模式,他說“EditorConfig 可以維護其屬性的不變數并進行獨立測驗。而且由于 EditorConfig 是一種值型別,因此對 EditorConfig 的屬性的任何更改,就像它的進展一樣,它作為對 EditorConfig 本身的更改可見。”
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/430547.html
上一篇:HStack中的中心元素
