user2732722
user2732722

Reputation: 655

Getting assertion failure when deleting the last item from a UICollectionView

I am deleting items in a UICollectionView with the following code:

func DeleteItem(indexPath: NSIndexPath) { 

    // remove from the data source
    myList.removeObjectAtIndex(indexPath.item)

    // remove the item from the collection view
    self.collectionView!.performBatchUpdates({
        self.collectionView?.deleteItemsAtIndexPaths([indexPath])
    }, completion: nil)
}     

This works fine except if I want to delete the last item in the list, even if the list is not empty. I get the following assertion failure:

'NSInternalInconsistencyException', reason: 'attempt to delete item 4 from section 0 which only contains 4 items before the update'

I debugged it and it seems that the delete code checks the number of items in the data source by calling:

collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int)

when you try to delete the last item, because you have deleted one from the data source the number of items in the data source becomes equal to the index that you are trying to delete in the UI collection. In this assertion example, I'm attempting to delete the last item with index 4 from a data source that originally had 5 items, when I remove the item from the data source, the number of items becomes 4, which is equal to the index of the item to be deleted from the UI, so the delete code raises assertion.
I don't know how to get around this. The correct way is to delete the item from the datasource first and then from the collection. Doing it the other way around gives you other assertions. So what is the right way to do this? Thanks!

Upvotes: 2

Views: 915

Answers (3)

TylerJames
TylerJames

Reputation: 971

I encountered this same problem and found a solution:

In your code that handles deletion you need to check if you are deleting the last item in the section. If you are deleting the last item then you will also need to reload the section. Something like this:

__weak typeof(self)weakSelf = self;
[items removeObjectAtIndex:index];
[self.collectionView performBatchUpdates:^{
    [weakSelf.collectionView deleteItemsAtIndexPaths:@[[NSIndexPath indexPathForRow:index inSection:sectionIndex]]];
    if (items.count == 0) {
       [weakSelf.collectionView reloadSections:[NSIndexSet indexSetWithIndex:sectionIndex]];
    }
} completion:nil];

Upvotes: 1

user2732722
user2732722

Reputation: 655

I resolved my problem. It wasn't about the way that I was deleting an item. The above mechanism is correct. Somewhere else in the code I was calling reloadItemsAtIndexPaths after the delete. I still don't know why that would cause the assertion, but removing reloadItemsAtIndexPaths solved the issue without compromising my program. It seems that I didn't need to have that in the first place.

Upvotes: 2

Sande Harsa
Sande Harsa

Reputation: 101

Try removing the item from the list inside the updates block.

Upvotes: 0

Related Questions