SwiftUI 中的 MVVM 模型

Jan*_*els 3 view mvvm viewmodel swift swiftui

我想根据 MVVM 将视图与视图模型分开。如何在 SwiftUI 中创建模型?我读到应该使用结构而不是类。

\n

作为一个例子,我有一个公园模型,您可以在其中种植树木:

\n
// View Model\nstruct Park {\n  var numberOfTrees = 0\n  func plantTree() {\n    numberOfTrees += 1 // Cannot assign to property: \'self\' is immutable\n  }\n}\n\n// View\nstruct ParkView: View {\n  var park: Park\n  var body: some View {\n    // \xe2\x80\xa6\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

阅读有关@State此类内容的内容,这些内容使结构有些可变,所以我尝试:

\n
struct Park {\n  @State var numberOfTrees = 0 // Enum \'State\' cannot be used as an attribute\n  func plantTree() {\n    numberOfTrees += 1 // Cannot assign to property: \'self\' is immutable\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

@State我确实直接在 a 中使用成功View。但这并不能帮助分离视图模型代码。

\n

我可以使用class

\n
class Park: ObservableObject {\n  var numberOfTrees = 0\n  func plantTree() {\n    numberOfTrees += 1\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

\xe2\x80\xa6但是这样我在使用嵌套在另一个视图模型中的视图模型时就会遇到麻烦,比如City

\n
struct City {\n  @ObservedObject var centerPark: Park\n}\n
Run Code Online (Sandbox Code Playgroud)\n

centerPark不会发布\xe2\x80\x99中的更改,因为Park现在是引用类型(至少不在我的测试或此处)。另外,我想知道您如何使用struct.

\n

Chr*_*isR 5

作为起点:

// 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()
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)