問(wèn)題:collection view 在reloadData之后,找不到 cell
今天碰到的一個(gè)問(wèn)題:app 主界面是一個(gè) collection view,當(dāng)數(shù)據(jù)源增加一個(gè)數(shù)據(jù)時(shí),我需要立即刷新視圖权均,并打開相應(yīng)的 cell岩睁。
于是我寫了如下代碼,
[self.collectionView reloadData];
UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:indexPath];
[self performSegueWithIdentifier:openInFileIdentifier sender:cell];
debug 發(fā)現(xiàn)獲取的 cell 是 nil,在斷點(diǎn)處查看 collection view 的 visibleCells 也是空的纵散。我猜測(cè) reloadData 背后開啟了分線程來(lái)處理這個(gè)事情,所以 reloadData 方法返回的時(shí)候隐圾,視圖并沒(méi)有完成刷新伍掀。
解決方案
去 stackOverFlow 上搜索一下,找到了一個(gè)解決方案:
UICollectionView 有一個(gè)方法翎承,
- (void)performBatchUpdates:(void (^)(void))updates completion:(void (^)(BOOL finished))completion; // allows multiple insert/delete/reload/move calls to be animated simultaneously. Nestable.
這個(gè)方法會(huì)在第一個(gè) block 中處理 insert/delete/reload/move 等操作硕盹,等操作完成之后會(huì)執(zhí)行第二個(gè)block。更新代碼叨咖,問(wèn)題解決瘩例。
[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)foo
{
needOpenCellIndexPath = ...;
[self.collectionView performBatchUpdates:^{
[self.collectionView reloadItemsAtIndexPaths:@[needOpenCellIndexPath]];
} completion:^(BOOL finished) {
UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:needOpenCellIndexPath];
if (cell) {
[self performSegueWithIdentifier:RPAOpenMapSegueIdentifier sender:cell];
} else {
// Start scrolling to the target cell.
[self.collectionView selectItemAtIndexPath:needOpenCellIndexPath animated:YES scrollPosition:UICollectionViewScrollPositionTop];
}
}];
}
#pragma mark - scroll view deleagte
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
if (needOpenCellIndexPath) {
UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:needOpenCellIndexPath];
[self performSegueWithIdentifier:openInFileIdentifier sender:cell];
}
needOpenCellIndexPath = nil;
}
#pragma mark -
測(cè)試炬守,問(wèn)題完美解決。
歡迎來(lái)我的個(gè)站逛逛: http://alexyu.me/