当 SearchController 处于活动状态时,CollectionView 自定义单元格无法正确更新

CollectionView Custom Cell Does Not Update Correctly When SearchController is Active

我有一个带有搜索控制器和自定义单元格的集合视图。当我在搜索未激活的情况下在单元格中进行编辑时,所有内容都会毫无问题地更新。但是当搜索控制器处于活动状态时,我的编辑不会正确重新加载。这是我的一些代码。

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    //SEARCH
    if searchController.isActive{
        return searchResults.count
    }else{
    return products.count
    }
    //SEARCH
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: Identifiers.ProductCell, for: indexPath) as? ProductCell {

        //SEARCH
        // Determine if we get the products from search result or the original array
        let searchItem = (searchController.isActive) ? searchResults[indexPath.item] : products[indexPath.item]

        cell.product = searchItem
        cell.delegate = self

        return cell
    }
    return UICollectionViewCell()
}

我有一个用于在单元格中填充信息的监听器,这是我的监听器代码:

func setProductsListener(){

    listener = ProductsService.getProducts { [weak self] change, product in

        guard let self = self else { return }
        switch change.type {
        case .added:
            self.onDocumentAdded(change: change, product: product)
        case .modified:
            self.onDocumentModified(change: change, product: product)
        case .removed:
            self.onDocumentRemoved(change: change)

        @unknown default: break
        }
    }
}

这里是我的更改重新加载到 collectionView 的地方:

    func onDocumentAdded(change: ProductChange, product: Product){
        let newIndex = Int(change.newIndex)
        products.insert(product, at: newIndex)
        collectionView.insertItems(at: [IndexPath(item: newIndex, section: 0)])

        // calculate and set title for cart subtotal
        cartBtn.setTitle(subtotal.penniesToFormattedCurrency(), for: .normal)
        cartBtn.sizeToFit()
    }

    func onDocumentModified(change: ProductChange, product: Product) {

        if change.newIndex == change.oldIndex {

            // Item changed, but remained in the same position
            let index = Int(change.newIndex)
            products[index] = product

            (collectionView.cellForItem(at: IndexPath(item: index, section: 0)) as? ProductCell)?.product = product

            // calculate and set title for cart subtotal
            cartBtn.setTitle(subtotal.penniesToFormattedCurrency(), for: .normal)
            cartBtn.sizeToFit()
        } else {

            // Item changed and changed position
            let oldIndex = Int(change.oldIndex)
            let newIndex = Int(change.newIndex)
            products.remove(at: oldIndex)
            products.insert(product, at: newIndex)

            collectionView.moveItem(at: IndexPath(item: oldIndex, section: 0), to: IndexPath(item: newIndex, section: 0))

            // calculate and set title for cart subtotal
            cartBtn.setTitle(subtotal.penniesToFormattedCurrency(), for: .normal)
            cartBtn.sizeToFit()
        }
    }

    func onDocumentRemoved(change: ProductChange){
        let oldIndex = Int(change.oldIndex)
        products.remove(at: Int(oldIndex))
        collectionView.deleteItems(at: [IndexPath(item: oldIndex, section: 0)])

        // calculate and set title for cart subtotal
        cartBtn.setTitle(subtotal.penniesToFormattedCurrency(), for: .normal)
        cartBtn.sizeToFit()
    }

所以这是我的 UI 在搜索控制器未激活时的样子:

当我开始搜索并输入单词 "As.."(尝试搜索 Asparagus)时,我得到了这个结果:

到目前为止我没有问题。但是,一旦我尝试在搜索控制器处于活动状态时单击 "plus" 或 "minus" 来更改数量;错误的索引也会更新;请看下面的屏幕截图。不仅索引 0 为 Asparagus 更新;索引 2 也更新为相同的项目,芦笋。

我很确定问题出在下面的代码中,一旦修改完成;当搜索控制器处于活动状态时,错误的索引也会得到更新。知道如何更改下面的代码以便在搜索控制器处于活动状态时更新正确的索引吗?

func onDocumentModified(change: ProductChange, product: Product) {

    if change.newIndex == change.oldIndex {

        // Item changed, but remained in the same position
        let index = Int(change.newIndex)
        products[index] = product

        (collectionView.cellForItem(at: IndexPath(item: index, section: 0)) as? ProductCell)?.product = product

        // calculate and set title for cart subtotal
        cartBtn.setTitle(subtotal.penniesToFormattedCurrency(), for: .normal)
        cartBtn.sizeToFit()
    }

我通过将以下内容添加到 func onDocumentModified 来修复它:

        if searchController.isActive {

            for item in searchResults {

                if item.id == product.id {
                    let searchedItemIndex = Int((searchResults.firstIndex(of: item))!)

                    (collectionView.cellForItem(at: IndexPath(item: searchedItemIndex, section: 0)) as? ProductCell)?.product = product
                }
            }

        } else {

            collectionView.reloadItems(at: [IndexPath(item: index, section: 0)])                
        }