【问题标题】:UICollectionView move items to new sectionUICollectionView 将项目移动到新部分
【发布时间】: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 但将任何移动排除在新插入的部分中,我显然会在这些部分中获得无效的项目数。

有人有解决这个问题的方法吗?

【问题讨论】:

标签: ios objective-c uicollectionview


【解决方案1】:

我按照 john1034 的链接找到了一个非常棘手的方法。您必须将工作分成三个步骤:

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

当然有很多行可以进一步改进。尤其是搜索功能相当低效...

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    • 1970-01-01
    • 2017-07-29
    相关资源
    最近更新 更多