UICollectionView将项目移动到新的部分

我遇到了一个UICollectionViewanimation的严重问题,类似于这里提到的问题: UICollectionView在重新安排部分之间的项目时崩溃

比方说,我有一个UICollectionView与5个不同的部分,每个10个单元格。 我想用animation更新CollectionView,所以单元格将被重新sorting为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和委托在理论上正常工作。 除了它还没有animation…

如果我执行insertSections,deleteSections和moveItemAtIndexPath (这应该工作,因为单元格只重新排列),我得到这个小错误: 不能将一行移动到新插入的部分(5)

如果我执行insertSections,deleteSections和moveItemAtIndexPath但排除任何移动到一个新插入的部分,我显然在节中的项目数量无效。

有没有人有这个问题的解决scheme?

我跟着john1034的链接,想出了一个相当棘手的方法来做到这一点。 你必须分三步完成工作:

  1. 如有必要添加新的部分。 新的部分将首先是空的。
  2. 添加,删除和移动新的和现有的部分内的单元格。
  3. 如有必要,删除部分。

可以肯定的是有很多线路可以进一步改进。 尤其是searchfunction相当低效

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