微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 collectionView.deleteItems 为什么我们首先需要 cell.indexPath?

如何解决在 collectionView.deleteItems 为什么我们首先需要 cell.indexPath?

我成功地从我的 collectionView 和数据源中删除了项目,但是在删除后没有调用 cellForItemAt,所以我的索引变得一团糟。即使我在删除后立即手动调用 collectionView.reloadData(),它也不起作用。

然而,如果我在 collectionView.reloadData() 之前的任何时间调用 collectionView.deleteItems(at: [indexPath]),它会被调用,但显然对我没有任何好处。不知道我做错了什么,请看一看:

class ChipView: UIView {        
    var chips: [ChipModel]?

    lazy var collectionView: UICollectionView = {
         let flowLayout = LeftAlignedCollectionViewFlowLayout()
         flowLayout.scrollDirection = .vertical

         let result = UICollectionView(frame: frame,collectionViewLayout: flowLayout)
         result.translatesAutoresizingMaskIntoConstraints = false
         result.register(Chip.self,forCellWithReuseIdentifier: "Cell")
         result.delegate = self
         result.dataSource = self
         result.backgroundColor = .clear
         result.isAccessibilityElement = false
         return result
     }()

    func deleteItem(_ sender: Chip) {
        guard let chipsArray = chips,!chipsArray.isEmpty,let indexPath = sender.indexPath else { return }

        // 1. remove value from source of truth
        chips?.remove(at: indexPath.row)
        // 2. delete item from collection view
        collectionView.deleteItems(at: [indexPath])
        // Todo: - figure out why cellForItemAt isn't getting called after collectionView.deleteItems... Needs to update the indexPath
        collectionView.reloadData()
     }

extension ChipView: UICollectionViewDataSource {
     public func collectionView(_: UICollectionView,numberOfItemsInSection _: Int) -> Int {
         return chips?.count ?? 0
}

     public func collectionView(_ collectionView: UICollectionView,cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
         let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell",for: indexPath) as! Chip
         cell.indexPath = indexPath

         if let chip = chips?[indexPath.row] {
            cell.setupChip(title: chip.title,icon: chip.icon,chipState: chip.chipState)
         }

         return cell
     }
  }

解决方法

为什么我们首先需要 cell.indexPath?

我假设您稍后在单元格内的某个按钮点击上使用 indexPath 值以从数据源 chips?[indexPath.row] 获取模型值。

如果答案是肯定的,那么我认为避免这种情况的一种方法可能就这么简单。

public func collectionView(_ collectionView: UICollectionView,cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell",for: indexPath) as! TruChip
    
    /* Stop doing this
    cell.indexPath = indexPath
    */

    if let chip = chips?[indexPath.row] {
        /* Stop doing this
        cell.setupTruChip(title: chip.title,icon: chip.icon,chipState: chip.chipState)
        */
        cell.setupTruChip(chip)
    }

    return cell
}

/// Inside the cell
class TruChip: UICollectionViewCell {
    var currentChip: TruChipModel?

    func setupTruChip(_ chip: TruChipModel) {
        currentChip = chip
        self.setupTruChip(title: chip.title,chipState: chip.chipState)
    }
}

通过这种方法,您可以完全消除记住单元格上的 indexPath 的需要。单元格记住它在 UI 上表示的当前模型数据。

,

在删除之前添加批量更新为我修复它:

    collectionView.performBatchUpdates {
        collectionView.deleteItems(at: [indexPath])
    } completion: { (finished) in
        self.collectionView.reloadData()
    }

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。