更新无效:第0部分中的商品数量无效。

时间:2017-09-10 12:45:01

标签: swift swift3 uicollectionview tvos

最近我收到以下错误:

  

致命异常:NSInternalInconsistencyException   无效更新:第0部分中的项目数无效。更新后的现有部分中包含的项目数(13)必须   等于该部分之前包含的项目数   更新(12),加上或减去插入或删除的项目数   从该部分(0插入,0删除)和加号或减号   物品移入或移出该部分(0移入,0移出)。

错误发生在我的tvOS客户端的以下代码中:

 let removedIndexPaths = removedIndexes.map({ IndexPath(row: $0, section: 0) })
 let addedIndexPaths = addedIndexes.map({ IndexPath(row: $0, section: 0) })
 let updatedIndexPaths = updatedIndexes.map({ IndexPath(row: $0, section: 0) })

  self.collectionView?.performBatchUpdates({
      self.collectionView?.deleteItems(at: removedIndexPaths)
      self.collectionView?.insertItems(at: addedIndexPaths)
      }, completion: { _ in
          guard let collectionView = self.collectionView else {
              return
          }

          for indexPath in updatedIndexPaths {
              if let myCell = collectionView.cellForItem(at: indexPath) as? MyCollectionViewCell {
                  let item = self.dataManager.items[indexPath.row]
                  myCell.updateUI(item)
               }
          }

          let collectionViewLayout = self.collectionViewLayoutForNumberOfItems(self.dataManager.items.count)
          if collectionViewLayout.itemSize != self.collectionFlowLayout.itemSize {
                collectionView.setCollectionViewLayout(collectionViewLayout, animated: false)
          }
  })

我只在集合视图中使用了一个部分:

override func numberOfSections(in collectionView: UICollectionView) -> Int {
    return 1
}

我已经查看了几个关于同一主题的帖子,但是他们还没有解决我的问题,我的猜测是问题出在以下两行,但我不确定:

 self.collectionView?.deleteItems(at: removedIndexPaths)
 self.collectionView?.insertItems(at: addedIndexPaths)

请帮忙。

2 个答案:

答案 0 :(得分:5)

insertItems(at:)deleteItems(at:)的调用也必须伴随数据源的更改。

因此,在调用这些API之前,您需要更改数据源,即在调用insertItems之前将对象添加到其中,并在调用deleteItems之前从中删除对象

答案 1 :(得分:0)

找到一篇关于 UICollectionView invalid number of items 崩溃问题的非常好的文章 - https://fangpenlin.com/posts/2016/04/29/uicollectionview-invalid-number-of-items-crash-issue/

collectionView(_:numberOfItemsInSection:) 返回的项目计数应该与闭包内部所做的更新同步。考虑到这个想法,解决起来很容易,只需添加一个属性作为项目计数并在 performBatchUpdates 闭包中更新它

func updateItems(updates: [ItemUpdate]) {
collectionView.performBatchUpdates({
  for update in updates {
      switch update {
      case .Add(let index):
          collectionView.insertItemsAtIndexPaths([NSIndexPath(forItem: index, inSection: 0)])
          itemCount += 1
      case .Delete(let index):
          collectionView.deleteItemsAtIndexPaths([NSIndexPath(forItem: index, inSection: 0)])
          itemCount -= 1
      }
    }
  }, completion: nil)
}

对于 collectionView(_:numberOfItemsInSection:),我们不返回 items.count,而是返回由 performBatchUpdates 闭包手动维护的属性。

func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return itemCount
}