新手 Swift UI 问题 - 从模型 class 更新视图

Noob Swift UI question - Updating views from model class

我有我的 ItemModel 和我的 Contentview,但是当 运行 程序时,视图不会实时更新新数量。如何让模型和视图“交谈”

import Foundation
import SwiftUI

class Item: ObservableObject {
    var name: String
    @Published var qty: Int
    

    init(name: String, qty: Int) {
        self.name = name
        self.qty = qty
    }
    
}

var metzScissor = Item(name: "Metz Scissor", qty: 5)
import SwiftUI

struct ContentView: View {
    
    var body: some View {
        
        NavigationView {
        
        VStack {
            Text("Items In Stock")
                .font(.title)
                .padding()
            Spacer()
            NavigationLink (
                destination: ItemDetailView(),
             label: {
                 Text(metzScissor.name)
            })
            Spacer()
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

我是否需要在视图文件中创建我的模型实例 class?

通常,在@Published 属性中保存模型结构的 ObservableObject 是一个单例,您可以使用 App 结构体中的 environmentObject 修饰符将其传递到 View 结构层次结构中。这使得它在 ContentView 中可用,如果您声明 @EnvironmentObject var.

,当模型结构发生变化时,下面的每个视图和正文都将 运行

它是单例的原因是您可以有一个不同的单例,其中包含要在预览时使用的示例数据。我们不使用@StateObject 的原因是它在预览期间不是初始化的,并且当模型结构更改时,您通常不需要重新计算 App 结构体。

也许是这样的:

import SwiftUI

struct Item: Identifiable {
    let id = UUID()
    var name: String
    var qty: Int
    
    init(name: String, qty: Int) {
        self.name = name
        self.qty = qty
    }
}

class Model: ObservableObject {
    @Published items: [Item] = []

    static let shared = Model()

    static let preview: Model = {
        let metzScissor = Item(name: "Metz Scissor", qty: 5)
        return Model(items:[metzScissor])
    }()
}
import SwiftUI
@main
struct TestApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(Model.shared)
        }
    }
}
import SwiftUI

struct ContentView: View {
    @EnvironmentObject var model: Model

    var body: some View { 
        NavigationView {
            List{
                ForEach(model.items) item in
                 NavigationLink (
                    destination: ItemView(item: item),
                 label: {
                     Text(item.name)
                })
            }
            .navigationTitle("Items in Stock")
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
        .environmentObject(Model.preview)
    }
}