我遇到了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 ,一切正常,这意味着我的dataSource和委托在理论上正常工作。除了它还没有动画......
如果我执行 insertSections,deleteSections和moveItemAtIndexPath (这应该可以工作,因为单元格只能重新排列)我得到这个小错误: 无法将行移动到新插入的部分(5)
如果我执行 insertSections,deleteSections和moveItemAtIndexPath 但排除任何移动到新插入的部分,我显然会在部分中获得无效的项目数。
有没有人能解决这个问题?
答案 0 :(得分:0)
我遵循了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];
}