我遇到了一个奇怪的崩溃并试图整天修复它.
我有一个自定义的UICollectionViewLayout,它基本上增加了细胞的重力和碰撞.
我有一个自定义的UICollectionViewLayout,它基本上增加了细胞的重力和碰撞.
实施效果很好!
当我尝试使用以下命令删除一个单元格时会出现问题:[self.collectionView performBatchUpdates:].
它给我以下错误:
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}'
我的模型正在正确处理,我可以看到它从中删除项目!
要删除的项的indexPaths正在对象之间正确传递.
collectionView更新没有崩溃的唯一时间是我删除它上面的最后一个单元格,否则崩溃就会发生.
- (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]; }
处理单元属性的CollectionView委托是下面的基本委托.
- (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]; }
我已经尝试过的事情没有成功:
– 使布局无效
– 重新加载数据
– 从UIDynamicAnimator中删除行为,并在更新后再次添加它们
任何见解?
此存储库中提供了有问题的源代码.请检查一下. Code Repository
最好.
乔治.
解决方法
经过几周的努力,这个bug,我们的朋友@ david-h和@erwin的一些有用的见解,以及来自Apple的WWDR的一些电话和电子邮件,我能够解决这个问题.只想与社区分享解决方案.
>问题. UIKit Dynamics有一些帮助方法来处理集合视图,这些方法实际上并没有做我认为应该自动执行的内部操作,比如在执行某些使用performBatchUpdates:的操作时自动更新动态动画单元格.所以你必须根据WWDR手动完成,所以我们迭代更新的itens更新他们的NSIndexPaths,这样动态动画师可以给我们正确的单元更新.
>这个错误.即使对单元格插入/删除执行此indexPath更新,我也会在动画中出现大量随机崩溃和奇怪的行为.所以,我按照@erwin给出的一个提示,它包含在performBatchUpdates之后重新实例化UIDynamicAnimator:并且修复了这种情况下的所有问题.
所以代码.
- (void)removeItemAtIndexPath:(NSIndexPath *)itemToRemove completion:(void (^)(void))completion { UICollectionViewLayoutAttributes *attributes = [self.dynamicAnimator layoutAttributesForCellAtIndexPath:itemToRemove]; if (attributes) { [self.collisionBehavIoUr removeItem:attributes]; [self.gravityBehavIoUr removeItem:attributes]; [self.itemBehavIoUr removeItem:attributes]; // Fix the problem explained on 1. // Update all the indexPaths of the remaining cells NSArray *remainingAttributes = self.collisionBehavIoUr.items; for (UICollectionViewLayoutAttributes *attributes in remainingAttributes) { if (attributes.indexPath.row > itemToRemove.row) attributes.indexPath = [NSIndexPath indexPathForRow:(attributes.indexPath.row - 1) inSection:attributes.indexPath.section]; } [self.collectionView performBatchUpdates:^{ completion(); [self.collectionView deleteItemsAtIndexPaths:@[itemToRemove]]; } completion:nil]; // Fix the bug explained on 2. // Re-instantiate the Dynamic Animator self.dynamicAnimator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout:self]; [self.dynamicAnimator addBehavior:self.collisionBehavIoUr]; [self.dynamicAnimator addBehavior:self.gravityBehavIoUr]; [self.dynamicAnimator addBehavior:self.itemBehavIoUr]; } }
我开了一个雷达解释了这个问题,希望Apple能够在未来的更新中解决这个问题.如果有人复制它,它可以在OpenRadar.
谢谢大家.