UICollectionView 将项目移动到新部分
Posted
技术标签:
【中文标题】UICollectionView 将项目移动到新部分【英文标题】:UICollectionView move items to new section 【发布时间】:2015-11-12 22:58:03 【问题描述】:我在 UICollectionView 的动画上遇到了严重的问题,类似于这里提到的问题:UICollectionView crashes when rearranging items between sections
假设我有一个包含 5 个不同部分的 UICollectionView,每个部分有 10 个单元格。 我想用动画更新 CollectionView,因此单元格将重新排序为 10 个部分。不会添加包含新内容的单元格,也不会删除现有单元格。
因此我正在执行批量更新:
[_resultCollectionView performBatchUpdates:^
[_resultCollectionView insertSections:insertSections];
[_resultCollectionView deleteSections:deleteSections];
//[_resultCollectionView insertItemsAtIndexPaths:insertIndexPaths];
//[_resultCollectionView deleteItemsAtIndexPaths:deleteIndexPaths];
for (all items which need to be moved...)
[_resultCollectionView moveItemAtIndexPath:sourcePath toIndexPath:destinationPath];
completion:^(BOOL finished)
//[_resultCollectionView reloadData];
nil;
];
如果我在执行块后执行 insertSections、deleteSections、insertItemsAtIndexPath、deleteItemsAtIndexPath 和 reloadData,一切正常,这意味着我的数据源和委托在理论上可以正常工作。除了它还没有动画...
如果我执行 insertSections、deleteSections 和 moveItemAtIndexPath(这应该可以工作,因为单元格只会重新排列)我会遇到这个小错误: 无法将行移动到新插入的部分 (5)
如果我执行 insertSections、deleteSections 和 moveItemAtIndexPath 但将任何移动排除在新插入的部分中,我显然会在这些部分中获得无效的项目数。
有人有解决这个问题的方法吗?
【问题讨论】:
你检查过这个问题吗?我觉得@sponessuck 的答案可以解决您的问题。 ***.com/questions/26299502/… 【参考方案1】:我按照 john1034 的链接找到了一个非常棘手的方法。您必须将工作分成三个步骤:
-
如有必要,添加新部分。新部分将首先为空。
在新的和现有的部分中添加、删除和移动单元格。
必要时删除部分。
当然有很多行可以进一步改进。尤其是搜索功能相当低效...
static BOOL addingSections = NO;
static BOOL updatingCollectionView = NO;
static BOOL removingSections = NO;
- (void)reloadResultCollectionView
//IndexUnloadedArray: a link to my CollectionViewData before the update
//IndexArray: a link to my CollectionViewData after the update
//start only if something changed
if (![IndexArray isEqual:IndexUnloadedArray])
NSMutableIndexSet *deleteSections = [[NSMutableIndexSet alloc] init];
NSMutableIndexSet *insertSections = [[NSMutableIndexSet alloc] init];
NSMutableArray *deleteIndexPaths = [[NSMutableArray alloc] init];
NSMutableArray *insertIndexPaths = [[NSMutableArray alloc] init];
//step 1 - add collectionView sections
for (int i = 0; i < IndexArray.count; i++)
if (i >= IndexUnloadedArray.count)
[insertSections addIndex:i];
NSLog(@"insert sections:%@", insertSections);
_sectionAmount = (int)_distanceUnloadedArray.count + (int)insertSections.count;
addingSections = YES;
[_resultCollectionView performBatchUpdates:^
[_resultCollectionView insertSections:insertSections];
completion:^(BOOL finished)
nil;
];
addingSections = NO;
//step 2 - update collectionView
//adding cells if there are not enough
for (int i = 0; i < IndexArray.count; i++)
for (int j = 0; j < (int)[[IndexArray objectAtIndex:i] count]; j++)
NSNumber *searchIndex = [[IndexArray objectAtIndex:i] objectAtIndex:j];
bool found = NO;
for (int k = 0; k < IndexUnloadedArray.count; k++)
if ([[IndexUnloadedArray objectAtIndex:k] containsObject:searchIndex])
found = YES;
k = (int)IndexUnloadedArray.count;
if (!found)
[insertIndexPaths addObject:[NSIndexPath indexPathForRow:j inSection:i]];
NSLog(@"insert cells:%@", insertIndexPaths);
//deleting cells if there are too many
for (int i = 0; i < IndexUnloadedArray.count; i++)
if (![deleteSections containsIndex:i])
for (int j = 0; j < (int)[[IndexUnloadedArray objectAtIndex:i] count]; j++)
NSNumber *searchIndex = [[IndexUnloadedArray objectAtIndex:i] objectAtIndex:j];
bool found = NO;
for (int k = 0; k < IndexArray.count; k++)
if ([[IndexArray objectAtIndex:k] containsObject:searchIndex])
found = YES;
k = (int)IndexArray.count;
if (!found)
[deleteIndexPaths addObject:[NSIndexPath indexPathForRow:j inSection:i]];
NSLog(@"deleting cells:%@", deleteIndexPaths);
updatingCollectionView = YES;
[_resultCollectionView performBatchUpdates:^
[_resultCollectionView insertItemsAtIndexPaths:insertIndexPaths];
[_resultCollectionView deleteItemsAtIndexPaths:deleteIndexPaths];
for (int i = 0; i < IndexUnloadedArray.count; i++)
for (int j = 0; j < [[IndexUnloadedArray objectAtIndex:i] count]; j++)
NSIndexPath *sourcePath = [NSIndexPath indexPathForRow:(j) inSection:i];
NSNumber *searchIndex = [[IndexUnloadedArray objectAtIndex:i] objectAtIndex:j];
NSIndexPath *destinationPath;
for (int k = 0; k < IndexArray.count; k++)
if ([[IndexArray objectAtIndex:k] containsObject:searchIndex])
NSInteger *row = [[IndexArray objectAtIndex:k] indexOfObject:searchIndex];
destinationPath = [NSIndexPath indexPathForItem:row inSection:k];
if (sourcePath != destinationPath)
NSLog(@"moving cell from %ld.%ld to %ld.%ld (%@)", (long)sourcePath.section, (long)sourcePath.row, (long)destinationPath.section, (long)destinationPath.row);
[_resultCollectionView moveItemAtIndexPath:sourcePath toIndexPath:destinationPath];
else
NSLog(@"object %ld.%ld stays in position", (long)sourcePath.section, (long)sourcePath.row);
completion:^(BOOL finished)
nil;
];
updatingCollectionView = NO;
//step 3 - deleting sections if there are too many
for (int i = 0; i < IndexUnloadedArray.count; i++)
if (i >= IndexArray.count)
[deleteSections addIndex:i];
NSLog(@"delete sections:%@", deleteSections);
_sectionAmount = (int)_distanceArray.count;
removingSections = YES;
[_resultCollectionView performBatchUpdates:^
[_resultCollectionView deleteSections:deleteSections];
completion:^(BOOL finished)
//update table header and footer
[_resultCollectionView reloadData];
];
removingSections = NO;
- (NSInteger)numberOfSectionsInCollectionView: (UICollectionView *)collectionView
return _sectionAmount;
- (NSInteger)collectionView:(UICollectionView *)view numberOfItemsInSection:(NSInteger)section
if (addingSections)
if (section < _distanceUnloadedArray.count)
return [[_distanceUnloadedArray objectAtIndex:section] count];
else
return 0;
if (updatingCollectionView)
if (section < _distanceArray.count)
return [[_distanceArray objectAtIndex:section] count];
else
return 0;
if (removingSections)
return [[_distanceArray objectAtIndex:section] count];
return [[_distanceArray objectAtIndex:section] count];
【讨论】:
以上是关于UICollectionView 将项目移动到新部分的主要内容,如果未能解决你的问题,请参考以下文章
将 VB.NET 项目移动到新计算机后日期无法正常工作[关闭]
如何将 SQL Server LocalDB 数据库移动到新计算机