背景
之前在做項(xiàng)目的時(shí)候疟丙,遇見過reloadData后找不到某個(gè)cell的問題,這里做個(gè)總結(jié)重窟。
問題描述:
通過3D touch長按app圖標(biāo)载萌,彈出新建腦圖的選項(xiàng),然后點(diǎn)擊新建一張腦圖巡扇。接下來的步驟如下:先進(jìn)入app扭仁,在主界面創(chuàng)建一個(gè)新的思維導(dǎo)圖;刷新collection view厅翔;最后打開這張思維導(dǎo)圖(cell)進(jìn)入編輯界面乖坠。但是每次reloadData之后,找到不到對(duì)應(yīng)的cell刀闷,打開失敗熊泵。
如下代碼:
[self.collectionView reloadData];
UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:indexPath];
[self performSegueWithIdentifier:openInFileIdentifier sender:cell];
Debug 調(diào)試發(fā)現(xiàn)獲取的 cell 是 nil,在斷點(diǎn)處查看 collection view 的 visibleCells 也是空的涩赢。猜測 reloadData 背后開啟了分線程來處理這個(gè)事情戈次,所以 reloadData 方法返回的時(shí)候轩勘,視圖并沒有完成刷新筒扒。
解決方案:
使用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.
- 這個(gè)方法會(huì)在第一個(gè) block 中處理 insert/delete/reload/move 等操作;
- 等操作完成之后再執(zhí)行第二個(gè)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 不在可視范圍內(nèi)呢澄步?
如果 cell 剛好不在屏幕區(qū)域內(nèi)冰蘑,處于 visible 的狀態(tài),那么用上述方法依然會(huì)找不到 cell村缸。
首先 collection view 滾動(dòng)到目標(biāo) cell 處祠肥,然后在打開 cell。這里需要用到 scroll 的代理方法梯皿,以在滾動(dòng)動(dòng)畫結(jié)束的時(shí)候仇箱,找到目標(biāo) cell县恕。(滾動(dòng)結(jié)束才能確定目標(biāo) cell 是 visible 的。)你還需要定義一個(gè) indexPath 值以區(qū)分滾動(dòng)結(jié)束的時(shí)候是否需要打開cell剂桥,以及要打開哪個(gè) 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 - <UIScrollViewDeleagte>
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {
if (needOpenCellIndexPath) {
UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:needOpenCellIndexPath];
[self performSegueWithIdentifier:openInFileIdentifier sender:cell];
}
needOpenCellIndexPath = nil;
}