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

Posted

技术标签:

【中文标题】SwiftUI - 尽管使用了 @Published 和 @ObservedObject,但视图不会更新【英文标题】:SwiftUI - View doesn't update despite using @Published and @ObservedObject 【发布时间】:2020-09-19 15:27:05 【问题描述】:

我在使用 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)
                )

将狗添加到 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
            
        
    

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

感谢您的慷慨帮助!

【问题讨论】:

【参考方案1】:

我认为您想在Dog 中附加ArrayAddView,并在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

【讨论】:

【参考方案2】:

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

卡片视图:

struct CardView: View 

//MARK: - Properties

@Binding var dog: Dog

//MARK: - View

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

【讨论】:

以上是关于SwiftUI - 尽管使用了 @Published 和 @ObservedObject,但视图不会更新的主要内容,如果未能解决你的问题,请参考以下文章

如何在 SwiftUI 中使用 Firestore 创建子集合

macOS 应用程序上的 12000 个条目的 FetchRequest 非常慢,但 iOS 应用程序却没有 - 尽管代码相同(macOS Big Sur / iOS 14 上的 SwiftUI)

Swift之深入解析如何结合Core Data和SwiftUI

使用 SwiftUI 模拟 CSS flex-wrap 行为

列表元素上的 SwiftUI 清除背景

SwiftUI 嵌套列表不出现