8

我正在制作一个包含所有基本内容的集合视图,例如默认 FlowLayout、独特部分。
假设我正确使用collectionView:CellForItemAtIndexPath:和所有其他dataSource协议

我有mainData,它是一个字典数组(原始数据),mainDataReferenceOrderedmainDataNameOrdered并且是包含与(指向相同元素)mainDataQuantiteOrdered相同数据的其他数组。是控制器当前指向有序数据的数组指针。mainData
dataToDisplay

重新排序时,我只是更改集合视图批处理中的数据,如下所示:

[itemCollectionControl.collectionView performBatchUpdates:^{
        dataToDisplay = mainDataReferenceOrdered; //or any other ordered array
        [itemCollectionControl.collectionView reloadSections:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, itemCollectionControl.collectionView.numberOfSections)]];
    } completion:^(BOOL finished) {}];

但是集合会淡化所有单元格,即使它们已经可见,或者在正确的位置。

我阅读了有关 UICollectionView 的 Apple 文档,但我不知道我错过了什么。我还阅读了有关此的其他线程,但仍在寻找我必须做的事情。

批处理看起来如何知道要在单元格上应用哪个动画?


我的解决方案

这是我使用的最终代码,当然是我猜想的最接近的 iOS 编程指南。

[itemCollectionControl.collectionView performBatchUpdates:^{
    NSArray *oldOrder = dataToDisplay;
    dataToDisplay = mainDataNBContainersOrdered;
    for (NSInteger i = 0; i < oldOrder.count; i++) {
        NSIndexPath *fromIndexPath = [NSIndexPath indexPathForRow:i inSection:0];
        NSInteger j = [dataToDisplay indexOfObject:oldOrder[i]];
        NSIndexPath *toIndexPath = [NSIndexPath indexPathForRow:j inSection:0];
        [itemCollectionControl.collectionView moveItemAtIndexPath:fromIndexPath toIndexPath:toIndexPath];
    }
} completion:^(BOOL finished) {
    if (finished) {
        [itemCollectionControl.collectionView reloadData];
    }
}];

我只是浏览所有旧的订购项目,检查它们的新位置,然后应用它-[UICollectionView moveItemAtIndexPath:toIndexPath:]
仍然存在一些重复的单元格故障,但它在 iOS7 上看起来很好(而不是在 iOS6 上)。完成在 iOS7 上可能没用,我在 iOS6 洗牌的最后强制正确的顺序。

编辑

我想我找到了解决方案,但我不再能够对该项目进行测试。也许只添加 2 行代码就可以解决这个可怕的故障。

在任何呼唤之前-[UICollectionView moveItemAtIndexPath:toIndexPath:],呼唤-[UICollectionView beginUpdates],最后在所有动作之后-[UICollectionView endUpdates]

如果有人能够测试它发现它有效,请告诉我。

4

1 回答 1

6

The collection view doesn't know the identity of the items in your data model, so it has no way of knowing that they've moved. So you've got to explicitly tell the collection view where each cell moves to inside the batch update using moveItemAtIndexPath:toIndexPath:. You can calculate this yourself by looping over items in the from array and looking up their positions in the to array. Something like this (typed from memory, so sorry about any typos):

[itemCollectionControl.collectionView performBatchUpdates:^{
    for (NSInteger i = 0; i < mainDataReferenceOrdered.count; i++) {
        NSIndexPath *fromIndexPath = [NSIndexPath indexPathForRow:i inSection:0];
        NSInteger j = [mainDataNameOrdered indexOfObject:mainDataReferenceOrdered[i]];
        NSIndexPath *toIndexPath = [NSIndexPath indexPathForRow:j inSection:0];
        [itemCollectionControl.collectionView moveItemAtIndexPath:fromIndexPath toIndexPath:toIndexPath];
    }
} completion:^(BOOL finished) {}];

If you've got a lot (multiple thousands) of items, you might want to consider using sets for faster lookups.

A more generally applicable approach is to use something like TLIndexPathTools that can calculate the batch updates for you. Take a look at the Shuffle sample project.

于 2013-10-23T03:28:18.000 回答