视图未在类别菜单项选择 SwiftUI 上更新

View is not updating on Category Menu Item Selection SwiftUI

这是我的第一个 SwiftUI 应用程序。我做了很多搜索,但找不到解决方案。

我想展示不同类别的产品。为此,我有顶部栏水平滚动菜单。选择任何类别时,我想显示每个类别的产品。当加载第一类产品显示正确,但选择任何其他类别时,产品不会相应更新。但是,当我导航到任何其他视图并返回到该视图时,产品显示正确。

我试过的

我尝试了不同的视图来显示产品,例如 List/ScrollView。运气不好。

这是我的视图的完整代码

struct ProductListView: View {

    @State var data:[Product]
    @State private var categoryItems:[Product] = []
    @State private var uniqueCategories:[Product] = []
    @State private var numberOfRows:Int  = 0
    @State private var selectedItem:Int  = 0
    @State private var image:UIImage?

    @EnvironmentObject var authState: AuthenticationState

    @ViewBuilder
    var body: some View {

        NavigationView{
            VStack{
                ScrollView(.horizontal, showsIndicators: false) {
                    HStack {
                        ForEach(0..<self.data.removingDuplicates(byKey: { [=10=].category }).count) { i in
                            Text(self.data.removingDuplicates(byKey: { [=10=].category })[i].category)
                                .underline(self.selectedItem == i ? true:false, color: Color.orange)
                                .foregroundColor(self.selectedItem == i ? Color.red:Color.black)
                                //.border(Color.gray, width: 2.0)
                                .overlay(
                                    RoundedRectangle(cornerRadius: 0.0)
                                        .stroke(Color.init(red: 236.0/255.0, green: 240.0/255.0, blue: 241.0/255.0), lineWidth: 1).shadow(radius: 5.0)
                            ).padding(.horizontal)
                                //.shadow(radius: 5.0)

                                .onTapGesture {

                                    self.selectedItem = i
                                    _ = self.getSelectedCategoryProducts()
                                    print("Category Items New Count: \(self.categoryItems.count)")


                            }
                            Spacer()
                            Divider().background(Color.orange)
                        }
                    }
                }
                .frame(height: 20)

                Text("My Products").foregroundColor(Color.red).padding()

                Spacer()

                if(self.data.count == 0){
                    Text("You didn't add any product yet.")
                }

                if (self.categoryItems.count>0){

                    ScrollView(.vertical){

                        ForEach(0..<Int(ceil(Double(self.categoryItems.count)/2.0)), id: \.self){ itemIndex in
                            return HStack() {

                                NavigationLink(destination:ProductDetailView(index: self.computeIndexes(currentIndex: itemIndex,cellNo: 1), data: self.categoryItems, image: UIImage())){


                                    ProductTile(index: self.computeIndexes(currentIndex: itemIndex, cellNo: 1), data: self.categoryItems, image: UIImage())


                                }

                                NavigationLink(destination:ProductDetailView(index: self.computeIndexes(currentIndex: itemIndex,cellNo: 2), data: self.categoryItems, image: UIImage())){
                                    ProductTile(index: self.computeIndexes(currentIndex: itemIndex, cellNo: 2), data: self.categoryItems, image: UIImage())
                                }

                            }.padding(.horizontal)
                        }


                    }.overlay(
                        RoundedRectangle(cornerRadius: 10.0)
                            .stroke(Color.init(red: 236.0/255.0, green: 240.0/255.0, blue: 241.0/255.0), lineWidth: 1).shadow(radius: 5.0)
                    )
                }
            }

        }

        .onAppear(perform: {

            _ = self.getSelectedCategoryProducts()

            //print("Loading updated products....")
            if (self.authState.loggedInUser != nil){
                FireStoreManager().loadProducts(userId: self.authState.loggedInUser!.uid) { (isSuccess, data) in

                    self.data = data

                }
            }
        })

            .padding()


    }

    func populateUniqueCategories() -> [Product] {

        let uniqueRecords = self.data.reduce([], {
            [=10=].contains() ? [=10=] : [=10=] + []
        })

        print("Unique Items: \(uniqueRecords)")

        return uniqueRecords
    }

    func getSelectedCategoryProducts() -> [Product] {

        var categoryProducts:[Product] = []

        self.data.forEach { (myProduct) in
            if(myProduct.category == self.populateUniqueCategories()[selectedItem].category){
                categoryProducts.append(myProduct)
            }
        }
        self.categoryItems.removeAll()
        self.categoryItems = categoryProducts
        return categoryProducts
    }
    func computeIndexes(currentIndex:Int, cellNo:Int) -> Int {
        var resultedIndex:Int = currentIndex

        if (cellNo == 1){
            resultedIndex = resultedIndex+currentIndex
            print("Cell 1 Index: \(resultedIndex)")
        }else{
            resultedIndex = resultedIndex + currentIndex + 1
            print("Cell 2 Index: \(resultedIndex)")
        }
        return resultedIndex
    }
}

这是数组扩展

    extension Array {
    func removingDuplicates<T: Hashable>(byKey key: (Element) -> T)  -> [Element] {
        var result = [Element]()
        var seen = Set<T>()
        for value in self {
            if seen.insert(key(value)).inserted {
                result.append(value)
            }
        }

        return result
    }
}

如果你能帮我解决这个问题,我将不胜感激。 最好的问候

原因是在使用静态范围 ForEach 构造函数时,它不希望有任何更改,这是设计使然,因此不会更新。

所以不用像

ForEach(0..<self.data.removingDuplicates(byKey: { [=10=].category }).count) { i in
       ^^^^^^ range !!

ForEach(0..<Int(ceil(Double(self.categoryItems.count)/2.0)), id: \.self){
        ^^^^ range

需要使用直接数据容器,如

ForEach(self.data.removingDuplicates(byKey: { [=12=].category }), id: \.your_product_id) { product in
        ^^^^^^^^^  array

注意:迭代时如果需要索引,可以使用.enumerated()容器,eg: