【问题标题】:UICollectionView crashes when rearranging items between sections重新排列部分之间的项目时,UICollectionView 崩溃
【发布时间】:2013-05-24 13:57:51
【问题描述】:

我在为 UICollectionView 中的部分之间设置动画时遇到问题,我的程序不断崩溃,这是怎么回事?

我有一个包含四个部分的集合视图:

0: A
1:乙
2:C
3:D

我想将其转换为只有三个具有相同项目的部分:

0: A
1:B,C
2:D

我想为这个转换制作动画:

// Initial state

NSArray *source = @[ @[@"A"], @[@"B"], @[@"C"], @[@"D"] ];


// Some data source methods

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    return [source[section] count];
}

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
    return [source count];
}


// Transformation: that works but I have to keep an empty section

source = @[ @[@"A"], @[@"B", @"C"], @[@"D"], @[] ];

[collection performBatchUpdates:^{
    [collection moveItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]
                        toIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]];
    [collection moveItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:1]
                        toIndexPath:[NSIndexPath indexPathForItem:0 inSection:1]];
    [collection moveItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:2]
                        toIndexPath:[NSIndexPath indexPathForItem:1 inSection:1]];
    [collection moveItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:3]
                        toIndexPath:[NSIndexPath indexPathForItem:0 inSection:2]];
} completion:nil];


// Transformation: that crashes!

source = @[ @[@"A"], @[@"B", @"C"], @[@"D"] ];

[collection performBatchUpdates:^{
    [collection moveItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]
                        toIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]];
    [collection moveItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:1]
                        toIndexPath:[NSIndexPath indexPathForItem:0 inSection:1]];
    [collection moveItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:2]
                        toIndexPath:[NSIndexPath indexPathForItem:1 inSection:1]];
    [collection moveItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:3]
                        toIndexPath:[NSIndexPath indexPathForItem:0 inSection:2]];
    [collection deleteSections:[NSIndexSet indexSetWithIndex:3]];
} completion:nil];

我不断遇到崩溃,可能是内部断言失败:Assertion failure in -[UICollectionView _endItemAnimations]...,或者有时更奇怪的是 malloc 错误:incorrect checksum for freed object...

如果我不打电话给deleteSections:,它也不起作用。如果我把它放在第一位,它不会改变任何事情。如果我删除具有相同源和目标的moveItemAtIndexPath:toIndexPath:,它不会改变任何东西。如果我不在批处理块中执行此操作,它显然会在第一个命令时崩溃。 我是不是忽略了什么?

【问题讨论】:

  • 您找到解决方案了吗?似乎在同一批更新中使用 moveItemAtIndexPath:toIndexPath: 和 deleteSections: 总是会导致崩溃,但需要确认。

标签: ios crash uicollectionview


【解决方案1】:

来自这个非常有趣的article 关于 UICollectionView 的摘录:

在批量更新块中插入新部分时,必须 不要将任何项目插入该部分 - 将被处理 含蓄地。实际上,将项目插入到新插入的部分 批量更新块会创建“幽灵”层,这些层会卡在 集合视图层层次结构。大概这只是一个错误 UICollectionView,因为这种行为没有记录,也没有例外 被抛出

知道了这一点,我发现删除部分和moveItemFromIndexPath:toIndexPath 也不能很好地协同工作也就不足为奇了。我猜这是“某种相同的错误”。

我使用的解决方案:

我在我应该删除的部分中放置了一个虚假的隐形单元格。这让我可以保持与moveItemFromIndexPath:toIndexPath: 相同的行为。当然,我相应地调整了我的数据源!

【讨论】:

    【解决方案2】:

    您是否尝试过类似的方法:

    source = @[ @[@"A"], @[@"B", @"C"], @[@"D"] ];
    
    [collection performBatchUpdates:^{
        [collection moveItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:2]
                            toIndexPath:[NSIndexPath indexPathForItem:1 inSection:1]];
        [collection deleteSections:[NSIndexSet indexSetWithIndex:2]];
    } completion:nil];
    

    【讨论】:

    • 实际上我认为问题是我们不能混合可能冲突的部分和项目更新。如果我们删除第 2 节,则意味着我们也删除了第 2 节中包含的项目,但我们已经要求移动第 2 节中的项目,所以我想我们不能同时移动和删除项目......我感觉唯一的解决方案是保持节数不变。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-03
    • 1970-01-01
    • 1970-01-01
    • 2022-09-29
    相关资源
    最近更新 更多