1

I'm trying to delete a cell from my UICollectionView. I'm using a custom layout, and the deletion happens in response to a long press gesture recognizer that I've added to the collection view. From what I've read, I need to update the data source first, then delete the cells, which is what I do. Everything goes smoothly until self.collectionView?.deleteItemsAtIndexPaths([indexPath]). I get the error:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UICollectionView received layout attributes for a cell with an index path that does not exist: {length = 2, path = 0 - 0}'

I've read other similar SO questions, but can't seem to get it working.

let book = self.booksForCurrentAuthor[indexPath.row]

self.booksForCurrentAuthor.removeAtIndex(indexPath.row)
self.collectionView?.deleteItemsAtIndexPaths([indexPath])

//Delete book from database

Edit

I don't think this is relevant, but in my custom layout object, I create a cache of UICollectionViewLayoutAttributes from within the prepareLayout() method. The cache is a dictionary, with separate arrays for attributes of Headers, Cells, Footers, and Decoration views.

cweber105
  • 535
  • 1
  • 4
  • 21

2 Answers2

2

I think your custom layout manager could actually well be the issue.

When you delete the cell from the collectionView you need to invalidate the existing layout, otherwise the layout manager will simply give you the same array of attributes in the cache that it originally calculated - including the layout for the cell that you have deleted, hence the error.

Once you have deleted the relevant entry from your data source, call cache.removeAll(), then call prepareLayout() again to refresh the layout cache. After that, call collectionView.reloadData() (and perhaps also layoutSubviews() and setNeedsDisplay) and that should fix your problem. notice you don't actually need to delete a cell as the collectionView will automatically load in what it needs from the dequeued stack of cells.

Let me know how you get on. All best.

Marcus
  • 2,153
  • 2
  • 13
  • 21
  • This is essentially correct. I didn't design the custom layout well, so it wasn't recreating and delivering attributes dynamically as the data changed. Once I updated a number of methods for account for changes in the data, it worked fine. Thank you. – cweber105 Sep 20 '16 at 14:09
0

Have you tried solution from Delete cell from UICollectionView ?

In your case it would be something like that:

[self.collectionView performBatchUpdates:^{
        let book = self.booksForCurrentAuthor[indexPath.row]
        self.booksForCurrentAuthor.removeAtIndex(indexPath.row) 
        self.collectionView?.deleteItemsAtIndexPaths([indexPath])
    } completion:nil];
Community
  • 1
  • 1
Kamilton
  • 696
  • 6
  • 12