我有一个带有部分(2个部分)的CollectionView。当我从第1节删除一个单元格时,其删除效果非常好。但是,当我从第0部分删除一个单元格时,我的应用程序崩溃了,并出现如下错误:
第0部分中的无效项目数。更新(5)之后现有部分中包含的项目数必须等于更新(5)前该部分中包含的项目数。从该部分插入或删除的项目数(已插入0,已删除1),以及正负部分移入或移出该部分的项目数(移入0,移出0)。与userInfo(空)
在从collectionView删除项目之前,我从performBatchUpdates中的数据源中删除该项目:
extension MainCollectionViewController: NSFetchedResultsControllerDelegate {
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
collectionView?.performBatchUpdates({ [weak self] in
guard let self = self else { return }
items = controller.fetchedObjects as! [Item]
items2 = items.chunked(into: 5)
self.collectionView?.deleteItems(at: [self.deletedItemIndex!])
})
}
}
extension Array {
func chunked(into size: Int) -> [[Element]] {
return stride(from: 0, to: count, by: size).map {
Array(self[$0 ..< Swift.min($0 + size, count)])
}
}
}
func chunked-是一个像这样对数组进行切片的功能(本节中有5个项目):
在分块之前:
[1,2,3,4,5,6,7,8,9,10]
分块后:
[
[1, 2, 3, 4, 5], // first section in collectionView
[6, 7, 8, 9, 10], // second section in collectionView
]
我使用以下功能将商品从核心数据填充到collectionView:
override func numberOfSections(in collectionView: UICollectionView) -> Int {
print("call numberOfSections")
//3
return items2.count
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
print("call numberOfItemsInSection, current section is \(section)")
//4
return items2[section].count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionViewCell
let item = items2[indexPath.section][indexPath.row]
cell.itemNameTextLabel.text = item.name
cell.itemImageView.image = UIImage(data: item.image! as Data)
return cell
}
}
当用户长按项目(单元格)时,将其从collectionView和CoreData中删除。删除过程在这里:
@objc func handleLongPress(gesture: UILongPressGestureRecognizer!) {
if gesture.state != .ended {
return
}
let p = gesture.location(in: self.collectionView)
if let indexPath = self.collectionView?.indexPathForItem(at: p) {
let fetchRequest: NSFetchRequest<Item> = Item.fetchRequest()
fetchRequest.predicate = NSPredicate(format: "name == %@", self.items2[indexPath.section][indexPath.row].name!)
do {
if let context = (UIApplication.shared.delegate as? AppDelegate)?.persistentContainer.viewContext {
let selectedItem = try context.fetch(fetchRequest)[0]
//save deleted item index in var that use it index in performBatchUpdatesBlock
deletedItemIndex = IndexPath(row: indexPath.row, section: indexPath.section)
context.delete(selectedItem)
do {
try context.save()
print("Save!")
} catch let error as NSError {
print("Oh, error! \(error), \(error.userInfo)")
}
}
} catch {
print(error.localizedDescription)
}
}
}
此过程的图像: enter image description here
我的项目,例如Apple Books应用程序。我想重复删除预订过程...
我的完整代码是here(GitHub)。请使用iPhone SE模拟器。我的数据位于items.plist文件中,并在首次运行应用程序时自动保存到CoreData。
我的代码哪里有错误?
答案 0 :(得分:0)
从CollectionView中删除时,还应该从基础数据数组(items2)中删除。
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
collectionView?.performBatchUpdates({ [weak self] in
guard let self = self else { return }
items = controller.fetchedObjects as! [Item]
items2 = items.chunked(into: 5)
for indexPath in self.deletedItemIndex! {
items2[indexPath.section].remove(at: indexPath.row)
}
self.collectionView?.deleteItems(at: [self.deletedItemIndex!])
})
}
答案 1 :(得分:0)
也许是问题在于您删除了第0部分的一项,并且在删除后第0部分仍具有相同的序号,这是因为您在每次删除后都“重新分配”了这些序号。