UICollectionView在部分之间重新布置项目时崩溃 [英] UICollectionView crashes when rearranging items between sections

查看:447
本文介绍了UICollectionView在部分之间重新布置项目时崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法在 UICollectionView 中的部分之间动画变化,我的程序会不断崩溃,它有什么问题?



我有一个集合视图,其中包含四个部分:


0:A

1:B

2:C

3:D


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


0:A

1:B,C

2:D


我想对这个转换进行动画处理:

  //初始状态

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


//一些数据源方法

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

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


//转换:工作,但我必须保留一个空段

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];


//转换:崩溃!

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];

我不断得到崩溃,或者内部断言失败: [UICollectionView _endItemAnimations] ... ,有时更奇怪,一个malloc错误:对于释放的对象不正确的校验和... p>

如果我不调用 deleteSections:,它也不工作。如果我放在第一,它不改变任何东西。如果我删除具有相同源和目标的 moveItemAtIndexPath:toIndexPath:,它不会更改任何内容。如果我不在一个批处理块,它显然崩溃在第一个命令。
我忽略了什么?

解决方案

这个非常有趣的一个摘录文章关于UICollectionView:


批处理更新块中的一个新的部分,必须
不插入任何项到该部分 - 将隐式处理
。事实上,在
中的一个新插入的部分中插入项目时,批量更新块创建了ghost层,这些层被卡在
集合视图层层次结构中。大概这是一个只是bug与
UICollectionView,因为这种行为没有记录,没有异常
抛出


知道这一点,我发现这并不奇怪,删除的部分和 moveItemFromIndexPath:toIndexPath 不能一起很好地工作。我想这是同样的错误。



我使用的解决方案



我把一个假的看不见的细胞放在我应该删除的部分。这允许我保持相同的行为,如果我做了一个 moveItemFromIndexPath:toIndexPath:。当然,我相应地修改了我的数据源!


I have trouble animating changes between sections in a UICollectionView, my program keeps crashing, what is wrong with it?

I have a collection view which has four sections:

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

I want to transform it to have only three sections with the same items:

0: A
1: B, C
2: D

And I want to animate this transformation:

// 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];

I keep getting crashes, either an internal assertion failure: Assertion failure in -[UICollectionView _endItemAnimations]..., or sometimes, even more weird, a malloc error: incorrect checksum for freed object....

If I don't call deleteSections: it doesn't work either. If I put first, it doesn't change anything. If I remove the moveItemAtIndexPath:toIndexPath: which have the same source and destination, it doesn't change anything. If I don't do it in a batch block, it obviously crashes at the first command. Did I overlook something?

解决方案

An extract from this very interesting article about UICollectionView:

When inserting a new section within the batch update block, one must not insert any items into that section – that will be handled implicitly. In fact, inserting items into a newly-inserted section in a batch update block creates "ghost" layers which get stuck in the collection view layer hierarchy. Presumably this is a just bug with UICollectionView, as this behavior is not documented and no exception is thrown

Knowing this, I find it not surprising at all that deleting of section and moveItemFromIndexPath:toIndexPath do not work well together either. I guess it's "kind of the same bug".

The solution I used:

I put a fake invisible cell in the section I should have deleted. That permitted me to keep the same behavior as if I had done a moveItemFromIndexPath:toIndexPath:. Of course, I adapted my datasource accordingly!

这篇关于UICollectionView在部分之间重新布置项目时崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆