微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

ios – 在performBatchUpdates上崩溃的CollectionView UIKit Dynamics:

我遇到了一个奇怪的崩溃并试图整天修复它.
我有一个自定义的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.

谢谢大家.

原文地址:https://www.jb51.cc/iOS/332915.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐