简体   繁体   English

修改 ObservableObject 中的列表对象后,我的视图没有更新

[英]My view doesn't update after modifying an object of a list inside an ObservableObject

I am new to SwiftUI.我是 SwiftUI 的新手。 Imagine I am building an app for a shop.想象一下,我正在为一家商店构建一个应用程序。 I have a view that is a list of the details of a product, and two buttons: Pin (add to favorites) and Delete .我有一个产品详细信息列表的视图,以及两个按钮: Pin (添加到收藏夹)和Delete

My question is about the Pin button (the Delete button works fine).我的问题是关于Pin按钮(删除按钮工作正常)。 When I click on it, the icon is supposed to change to a filled pin icon instead of the classic pin icon.当我单击它时,该图标应该变为填充的 pin 图标,而不是经典的 pin 图标。 And when I go back the previous view, listing the 5 latest products and the pinned products (in two different sections), this one is supposed to update and add the modified product to the pinned product list.当我返回之前的视图时,列出 5 个最新产品和固定产品(在两个不同的部分),这个应该更新并将修改后的产品添加到固定产品列表中。

But right now, the pin icon doesn't change at all (but does when I go back and come again to the product details view) and the previous view doesn't show the product in the pinned product list (and I can't check that it appears when I reload the view, because I can't go back and come again to this view as this is the main view).但是现在,图钉图标根本没有改变(但是当我返回并再次进入产品详细信息视图时会改变)并且之前的视图不会在固定的产品列表中显示产品(而且我不能检查它是否在我重新加载视图时出现,因为我无法返回并再次进入该视图,因为这是主视图)。

I used some tags to indicate that the view does modify the store and the products themselves as you can see below.我使用了一些标签来表明视图确实修改了商店和产品本身,如下所示。

So the view has an attribute for the product itself and one for the store — the repository that controls the list of all products:因此,视图具有产品本身的属性和商店的属性——控制所有产品列表的存储库:

struct DetailsView: View {
    @StateObject var store: Store
    @State var product: Product
    
    var body: some View {
        List {
            Section {
                VStack(alignment: .leading) {
                    Text(product.name)
                    
                    Text(product.brand)
                        .font(.subheadline)
                        .foregroundColor(.secondary)
                }
                .padding(.vertical, 6.0)
            } header: {
                Text("Product")
            }
            
            Section {
                Button {
                    product.pinned = !product.pinned
                } label: {
                    HStack {
                        if (product.pinned) {
                            Image(systemName: "pin.fill")
                            Text("Unpin")
                        } else {
                            Image(systemName: "pin")
                            Text("Pin")
                        }
                    }
                    .padding(.vertical, 6.0)
                }
                
                Button {
                    store.remove(product.id)
                } label: {
                    HStack {
                        Image(systemName: "trash")
                        Text("Delete")
                    }
                    .foregroundColor(.red)
                    .padding(.vertical, 6.0)
                }
            }
        }
        .navigationTitle(product.name)
        .navigationBarTitleDisplayMode(.inline)
    }
}

My store is only defined by one attribute, the list of products:我的商店仅由一个属性定义,即产品列表:

class Store: ObservableObject {
    @Published private var products: [Product]
    
    …
}

Finally, a product is defined by different attributes (name, brand, pinned):最后,产品由不同的属性(名称、品牌、固定)定义:

class Product: Identifiable {
    static private var count: Int = 0
    
    let id: Int
    @Published var name: String
    @Published var brand: String
    @Published var pinned: Bool = false
    
    …
}

To recap, my problem is: my current view is not updated (the pin button doesn't change) and my previous view is not updated when I go back to it (the product doesn't appear in the pinned products list).回顾一下,我的问题是:我当前的视图未更新(固定按钮未更改),并且当我返回之前的视图时未更新(该产品未出现在固定的产品列表中)。

Does anyone have an idea on how to fix this?有谁知道如何解决这个问题? Thank you very much.非常感谢。

PS附言
My previous view showing the pinned items is working fine except this.我之前显示固定项目的视图工作正常,除了这个。 I tested it by initializing my store with pinned items and they appear.我通过使用固定项目初始化我的商店来测试它,它们会出现。

You have 2 questions:你有2个问题:

1, the pin status of your current page does not change when you click the pin icon. 1、点击pin图标时,当前页面的pin状态不会改变。

Why?为什么? Because the Product class does not inherit ObservableObject class, so it cannot be observed.因为 Product 类没有继承 ObservableObject 类,所以不能被观察。 To fix it, inherit ObservableObject class.要修复它,请继承 ObservableObject 类。

class Product: ObservableObject, Identifiable {
   static private var count: Int = 0

   let id: Int
   @Published var name: String
   @Published var brand: String
   @Published var pinned: Bool = false

   …
}

And in your DetailsView, remember to observe product:在您的 DetailsView 中,记得观察产品:

struct DetailsView: View{
   @ObeservedObject product: Product
   ...
}

2, your previous page does not change when you click pin in current page. 2、在当前页面点击pin不会改变你之前的页面。

The reason is that although the Store class is an observabledObject, which means the published property "products" is observed by others, the object of the array "products" is "product", which is a class.原因是虽然Store类是observabledObject,也就是说发布的属性“products”被别人观察到了,但是数组“products”的对象是“product”,是一个类。

So actually the array "products" holds some pointers to "product".所以实际上数组“products”包含一些指向“product”的指针。 Even when the product's properties like "pined" changes, the pointer(address) does not change.即使像“pined”这样的产品属性发生变化,指针(地址)也不会改变。 So when someone observe the published "products", he will say "Oh, nothing happened. No need to refresh the view."所以当有人观察发布的“产品”时,他会说“哦,什么都没发生,不需要刷新视图”。

To fix it, in your previous view, you should observe the product, rather than the store.要修复它,在您之前的视图中,您应该观察产品,而不是商店。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM