SwiftUI - 尽管使用@Published 和@ObservedObject,但视图不会更新

SwiftUI - View doesn't update despite using @Published and @ObservedObject

我在使用 SwiftUI 更新我的应用程序的主页视图时遇到了问题。

所以,我有一个 Dog 结构体 (Dog.swift) :

struct Dog: Identifiable {

var id = UUID()
var name: String
var race: String
var age: Int
var gender: String
var sterile: Bool
var pictureURL: String
var location: String
var dogFriendly: Bool
var catFriendly: Bool
var childFriendly: Bool
var needsGarden: Bool
var isClean: Bool
}

我的目标是在 AddView.swift:

中按下这个按钮
@ObservedObject var viewModel = AddViewModel()
 ************** LONG UI CODE *******************
.navigationBarItems(trailing:
                    Button("Publish") {
                        viewModel.dogs.append(Dog(name: self.name, race: races[selectedRace], age: self.age, gender: genders[selectedGender], sterile: self.isSterile, pictureURL: "", location: "", dogFriendly: self.isDogFriendly, catFriendly: self.isCatFriendly, childFriendly: self.isChildFriendly, needsGarden: self.needsGarden, isClean: self.isClean))
                        print(viewModel.dogs)
                })

将 dogs 添加到 AddViewModel.swift:

中的 Dog 数组
class AddViewModel: ObservableObject {

@Published var dogs: [Dog] = []
}

然后在 CardView 中显示信息:

struct CardView: View {

//MARK: - Properties

@State var dog: Dog

//MARK: - View

var body: some View {
******* LONG UI CODE ********
}

并在我的 HomeView 中显示这些 CardView:

struct HomeView: View {

@ObservedObject var viewModel = AddViewModel()


var body: some View {
    ScrollView {
        VStack {
            ForEach(viewModel.dogs) { dog in
                CardView(dog: dog) // this doesn't work
                Text(dog.name) // this doesn't work neither
            }
        }
    }
}

}

有人可以帮我解决这个问题并就如何进行提供建议吗?

感谢您的慷慨帮助!

将@State 更改为@Bindig 将修复它。

卡片视图:

struct CardView: View {

//MARK: - Properties

@Binding var dog: Dog

//MARK: - View

var body: some View {
******* LONG UI CODE ********
}

我想你想在 AddView 内追加 DogArray,并在 HomeView 内显示更新后的数据。因此,您刚刚在每个视图中分别声明了 AddViewModel 的实例。视图中的两个实例不会相互观察。为了解决这个问题,我更喜欢使用 Singleton 模式。这是我的示例代码。

struct ContentView: View {
    @ObservedObject private var viewModel: AddViewModel = .sharedInstance
    @State private var showSheet = false
    var body: some View {
        NavigationView {
            ScrollView {
                ForEach(viewModel.dogs) { dog in
                    Text(dog.name)
                        .frame(height: 25)
                }
            }
            .navigationTitle("DogZ")
            .navigationBarItems(leading: Button(action: {
                showSheet.toggle()
            }, label: {
                Text("Show")
            }))
        }
        .sheet(isPresented: $showSheet, content: {
            AddView()
        })
    }
}

struct AddView: View {
    @ObservedObject private var viewModel: AddViewModel = .sharedInstance
    @Environment(\.presentationMode) var presentationMode
    var body: some View {
        NavigationView {
            Text("Sheet Add View")
                .navigationBarItems(trailing: Button(action: {
                    viewModel.dogs.append(Dog(name: "Blacky"))
                    presentationMode.wrappedValue.dismiss()
                }, label: {
                    Text("Add")
                }))
        }
    }
}


class AddViewModel: ObservableObject {
    @Published var dogs = [Dog]()
    static var sharedInstance = AddViewModel()
}

struct Dog: Identifiable {
    var id = UUID()
    var name: String
}