I'm stucked with a strange crash and trying to fix it all day long. I have a custom UICollectionViewLayout that basically adds gravity and collision behavious to the cells.
The implementation works great! The problem happens when I try to delete one cell using: [self.collectionView performBatchUpdates:].
It gives me the following error:
2013-12-12 21:15:35.269 APPNAME[97890:70b] *** Assertion failure in -[UICollectionViewData validateLayoutInRect:], /SourceCache/UIKit_Sim/UIKit-2935.58/UICollectionViewData.m:357
2013-12-12 20:55:49.739 APPNAME[97438:70b] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UICollectionView recieved layout attributes for a cell with an index path that does not exist: <NSIndexPath: 0x975d290> {length = 2, path = 0 - 4}'
My model is being handled correctly and I can see it removing the item from it!
The indexPaths of the item to delete is being passed correctly between objects. The only time the collectionView update doen't crash is when I delete the last cell on it, otherwise, the crash happens.
Here's the code I'm using to delete the cell.
- (void)removeItemAtIndexPath:(NSIndexPath *)itemToRemove completion:(void (^)(void))completion
{
UICollectionViewLayoutAttributes *attributes = [self.dynamicAnimator layoutAttributesForCellAtIndexPath:itemToRemove];
[self.gravityBehaviour removeItem:attributes];
[self.itemBehaviour removeItem:attributes];
[self.collisionBehaviour removeItem:attributes];
[self.collectionView performBatchUpdates:^{
[self.fetchedBeacons removeObjectAtIndex:itemToRemove.row];
[self.collectionView deleteItemsAtIndexPaths:@[itemToRemove]];
} completion:nil];
}
The CollectionView delegates that handles the cell attibutes are the basic ones below.
- (CGSize)collectionViewContentSize
{
return self.collectionView.bounds.size;
}
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
return [self.dynamicAnimator itemsInRect:rect];
}
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
return [self.dynamicAnimator layoutAttributesForCellAtIndexPath:indexPath];
}
Things I already tried with no success: - Invalidating the layout - Reloading the data - Removing the behaviours from the UIDynamicAnimator and adding them again after the update
Any insights?
A source code with the problem is available on this repository. Please check it out. Code Repository
Best. George.
After some weeks struggling with this bug, some helpful insights from our friends @david-h and @erwin and some calls and e-mails from Apple's WWDR, I was able to figure this issue out. Just wanna share the solution with the community.
The problem. UIKit Dynamics has some helper methods to work with Collection Views and these methods don't actually do some internal stuff that I think it should do automatically, like automatically update the dynamically animated cells when some action using performBatchUpdates: is performed. So you have to do it manually according to WWDR, so we iterate over the updated itens updating their NSIndexPaths so the the dynamic animator can give us proper updates on the cells.
The bug. Even doing this indexPath update on a cell insertion/deletion, I had lots of random crashes and strange behaviours with the animation. So, I followed a tip given by @erwin that consists on re-instantiate the UIDynamicAnimator after a performBatchUpdates: and that fixes up all the problems with this kind of situation.
So the code.
I opened a Radar explaining the issue expecting Apple to fix this on a future update. If anyone whats to duplicate it, It's available on OpenRadar.
Thank you everyone.