如何在UICollectionView reloadData后找到的某個cell

問題:collection view 在reloadData之后,找不到 cell

今天碰到的一個問題:app 主界面是一個 collection view,當數據源增加一個數據時,我需要立即刷新視圖,并打開相應的 cell。

于是我寫了如下代碼,

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

debug 發現獲取的 cell 是 nil,在斷點處查看 collection view 的 visibleCells 也是空的。我猜測 reloadData 背后開啟了分線程來處理這個事情,所以 reloadData 方法返回的時候,視圖并沒有完成刷新。

解決方案

去 stackOverFlow 上搜索一下,找到了一個解決方案:

UICollectionView 有一個方法,

- (void)performBatchUpdates:(void (^)(void))updates completion:(void (^)(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)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 -

測試,問題完美解決。


歡迎來我的個站逛逛: http://alexyu.me/


引用
stackoverflow : Animation Duration for UICollectionView selectItemAtIndexPath:animated:scrollPosition:

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 翻譯自“Collection View Programming Guide for iOS” 0 關于iOS集合視...
    lakerszhy閱讀 3,925評論 1 22
  • 最近將 UICollectionView 進行了一個全面的學習及總結,參考了網上大量的文章,把官方文檔進行了大概翻...
    varlarzh閱讀 21,556評論 3 94
  • 發現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,245評論 4 61
  • 人要是有了追求,就一樣了。 莫言追求文學夢,他獲得了諾貝爾文學獎。 李安追求電影夢,他獨身一人去美國,拍了《臥虎藏...
    東風東風閱讀 701評論 0 6