Swift - 如何在具有多个部分的 collectionView 上执行 BatchUpdates

Posted

技术标签:

【中文标题】Swift - 如何在具有多个部分的 collectionView 上执行 BatchUpdates【英文标题】:Swift -How to performBatchUpdates on a collectionView with multiple sections 【发布时间】:2019-07-12 12:55:52 【问题描述】:

我有一个 collectionView,它有 3 个部分,每个部分都有一个不同的单元格(将单元格的数据分成单独的部分比只有 1 个部分更容易)。

collectionView 的数据源中只有 1 个 dataModel,它会更新,但 我只需要在第一部分显示该更新(添加了一个新标签)。当我尝试运行collectionView.performBatchUpdates 时,整个布局变得一团糟,它从显示所有 3 个部分变为仅显示最后一个部分,前 2 个部分完全消失。这不是限制,因为当我弹出并推回布局时,新标签显示第一部分中的更新数据和其他 2 看起来很好的新标签是完美的。问题似乎发生在我运行执行批处理更新时

我试过了:

let updatedDataModel = ...

guard let indexOfItem = tableData.firstIndex(where:  $0.itemId == updatedDataModel.itemId ) else  return 

tableData[indexOfItem] = updatedDataModel

let indexPath = IndexPath(item: indexOfItem, section: 0)

UIView.animate(withDuration: 0) 

    self.collectionView.performBatchUpdates( [weak self] in

        self?.collectionView.reloadItems(at: [indexPath])
        self?.collectionView.layoutIfNeeded()

    )  (_) in
        print("success")
    

我试过了:

collectionView.performBatchUpdates(
    let indexSet = IndexSet(integer: 0)
    self.collectionView.reloadSections(indexSet)
, completion: nil)

我试过了:

let updatedDataModel = ...

guard let indexOfItem = tableData.firstIndex(where:  $0.itemId == updatedDataModel.itemId ) else  return 

tableData[indexOfItem] = updatedDataModel

let indexPath0 = IndexPath(item: indexOfItem, section: 0)
let indexPath1 = IndexPath(item: indexOfItem, section: 1)
let indexPath2 = IndexPath(item: indexOfItem, section: 2)

UIView.animate(withDuration: 0) 

    self.collectionView.performBatchUpdates( [weak self] in

        self?.collectionView.reloadItems(at: [indexPath0, indexPath1, indexPath2])
        self?.collectionView.layoutIfNeeded()

    )  (_) in
        print("success")
    

cellForItem:

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

    // *** this section is where the updated data (an additional label) needs to appear
    if indexPath.section == 0 

        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: topCell, for: indexPath) as! TopCell
        cell.dataModel = tableData[indexPath.item]
        return cell
    

    if indexPath.section == 1 

        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: middleCell, for: indexPath) as! MiddleCell
        cell.dataModel = tableData[indexPath.item]
        return cell
    

    if indexPath.section == 2 

        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: bottomCell, for: indexPath) as! BottomCell
        cell.dataModel = tableData[indexPath.item]
        return cell
    

    // if for some reason something goes wrong above but this NEVER runs
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: errorCell, for: indexPath) as! ErrorCell
    return errorCell

数据源:

func numberOfSections(in collectionView: UICollectionView) -> Int 
    return 3


func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 

    if section == 0 
        return 1
    

    if section == 1 
        return tableData.count
    

    if section == 2 
        return 1
    

    return 0

我哪里出错了?

【问题讨论】:

【参考方案1】:

不要使用collectionView.performBatchUpdates,而只需编写以下内容以仅在您想要的部分中重新加载数据:

let indexSet = IndexSet(integer: 0)       // Change integer to whatever section you want to reload
collectionView.reloadSections(indexSet)

如果你不想要这个UICollectionView reload 的任何动画,请使用:

UIView.performWithoutAnimation 
    // same code as above


祝你好运。

【讨论】:

我会发布 numberOfSections 和 numberOfItems,item 的大小对于每个部分都有很多事情要做,它不可读。 我在问题的底部添加了它 我认为您可能刚刚帮助我找出了导致问题的原因。给我几分钟,我现在正在尝试。 @LanceSamaria 一切似乎都很好,您是否尝试过记录(打印到控制台)一些随机值并查看是否在 cellForItemAt 方法中重新加载了部分? @LanceSamaria 部分的项目大小也可能存在一些问题,但正如您所说,您不想发布它,因为代码很乱,请检查它是否正常。

以上是关于Swift - 如何在具有多个部分的 collectionView 上执行 BatchUpdates的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Swift 在 Firebase 中创建具有多个属性的用户?

SWIFT:在具有多个部分的表视图中显示字典时,无法将具有标识符单元格错误的单元格出列

使用 Realm 和 Swift 的具有多个部分的 UITableView

UITableView 使用 Realm 和 Swift 具有多个按字母顺序排列的部分,多个标签与相同的数据连接

Swift 3:如何将内容包装在具有多个标签的 tableviewcell 中?

如何在 Swift 4 中使用 Alamofire 上传具有其他参数的多个图像