iOS开发——如何在UICollectionView reloadData后找到某个cell

背景

之前在做项目的时候,遇见过reloadData后找不到某个cell的问题,这里做个总结。

问题描述:

通过3D touch长按app图标,弹出新建脑图的选项,然后点击新建一张脑图。接下来的步骤如下:先进入app,在主界面创建一个新的思维导图;刷新collection view;最后打开这张思维导图(cell)进入编辑界面。但是每次reloadData之后,找到不到对应的cell,打开失败。

如下代码:

[self.collectionView reloadData];
UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:indexPath];
[self performSegueWithIdentifier:openInFileIdentifier sender:cell];

Debug 调试发现获取的 cell 是 nil,在断点处查看 collection view 的 visibleCells 也是空的。猜测 reloadData 背后开启了分线程来处理这个事情,所以 reloadData 方法返回的时候,视图并没有完成刷新。

解决方案:

使用UICollectionView提供的如下方法处理:

- (void)performBatchUpdates:(void (NS_NOESCAPE ^ _Nullable)(void))updates completion:(void (^ _Nullable)(BOOL finished))completion; // allows multiple insert/delete/reload/move calls to be animated simultaneously. Nestable.
  • 这个方法会在第一个 block 中处理 insert/delete/reload/move 等操作;
  • 等操作完成之后再执行第二个block。

更新代码,问题解决。

[self.collectionView reloadData];
[self.collectionView performBatchUpdates:^{
    [self.collectionView reloadItemsAtIndexPaths:@[indexPath]];
} completion:^(BOOL finished) {
    UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:indexPath];
    [self performSegueWithIdentifier:openInFileIdentifier sender:cell];
}];

如果 cell 不在可视范围内呢?

如果 cell 刚好不在屏幕区域内,处于 visible 的状态,那么用上述方法依然会找不到 cell。

首先 collection view 滚动到目标 cell 处,然后在打开 cell。这里需要用到 scroll 的代理方法,以在滚动动画结束的时候,找到目标 cell。(滚动结束才能确定目标 cell 是 visible 的。)你还需要定义一个 indexPath 值以区分滚动结束的时候是否需要打开cell,以及要打开哪个 cell。

代码如下:

NSIndexPath *needOpenCellIndexPath;

- (void)reloadCollectionViewAndOpenCellWithIndexPath {
    needOpenCellIndexPath = ...;
    [self.collectionView performBatchUpdates:^{
        [self.collectionView reloadItemsAtIndexPaths:@[needOpenCellIndexPath]];
    } completion:^(BOOL finished) {
        UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:needOpenCellIndexPath];
        if (cell) {
            [self performSegueWithIdentifier:LSLOpenMapSegueIdentifier sender:cell];
        } else {
            // Start scrolling to the target cell.
            [self.collectionView selectItemAtIndexPath:needOpenCellIndexPath animated:YES scrollPosition:UICollectionViewScrollPositionTop];
        }    
    }];
}

#pragma mark - 

- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {
    if (needOpenCellIndexPath) {
        UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:needOpenCellIndexPath];
        [self performSegueWithIdentifier:openInFileIdentifier sender:cell];
    }
    needOpenCellIndexPath = nil;
}

你可能感兴趣的:(iOS开发——如何在UICollectionView reloadData后找到某个cell)