Просмотр не обновляется при выборе пункта меню категории SwiftUI - PullRequest
1 голос
/ 04 мая 2020

enter image description here Это мое первое приложение SwiftUI. Я провел много поисков и не смог найти решение.

Я хочу отображать продукты из разных категорий. Для этого у меня есть меню с горизонтальной прокруткой на верхней панели. При выборе любой категории я хочу отображать продукты каждой категории. Когда при загрузке продукты первой категории отображаются правильно, но при выборе любой другой категории продукты не обновляются соответствующим образом. Однако, когда я перехожу к любому другому представлению и возвращаюсь к нему, продукты отображаются правильно.

Что я пробовал

Я пробовал разные представления для отображения продуктов, например Список / ScrollView. Не повезло.

Вот полный код моего View

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: { $0.category }).count) { i in
                            Text(self.data.removingDuplicates(byKey: { $0.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([], {
            $0.contains($1) ? $0 : $0 + [$1]
        })

        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
    }
}

Я был бы очень благодарен, если вы мне поможете разобраться в этом вопросе. С уважением

1 Ответ

0 голосов
/ 05 мая 2020

Причина в использовании конструктора Stati c range ForEach, который не ожидает каких-либо изменений по дизайну, поэтому не обновляется.

Таким образом, вместо использования like

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

и

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

необходимо использовать контейнер прямых данных, например

ForEach(self.data.removingDuplicates(byKey: { $0.category }), id: \.your_product_id) { product in
        ^^^^^^^^^  array

Примечание: если вам нужен индекс во время итерации, можно использовать .enumerated() для контейнера, например: в этом посте

...