iOS tableView reload時抖動問題處理

tableView的cell采用cell自適應(yīng)高度,并且各個cell高度不同的情況下,在reload時,tableView可能會發(fā)生異常抖動。
原因就是因為沒有實現(xiàn)返回高度的代理,tableView刷新渲染時,并不明確cell的高度具體會是多少,以及cell自適應(yīng)高度的機制問題??赡艿漠惓0l(fā)生邏輯就是系統(tǒng)先拿模糊高度進行渲染,當(dāng)cell高度確定后,又調(diào)整了高度,所以發(fā)生的抖動。

我的解決方式如下:
willDisplayCell時用字典緩存cell的高度-> estimatedHeightForRowAtIndexPath方法返回
用字典存儲cell出現(xiàn)后的高度,刷新時讓系統(tǒng)使用我們對于每個cell緩存的高度。

#pragma mark - 解決動態(tài)cell高度 reloadData刷新抖動的問題
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
   _estimatedRowHeightCache[indexPath] = @(cell.frame.size.height);
}

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
     return [_estimatedRowHeightCache[indexPath] floatValue] ?:50; // 為0時最好返回最接近的預(yù)估高度
}

tip:

1. 一般情況下不是動態(tài)變化的界面字典的key值可以用indexPath,而如果cell位置會動態(tài)變化,或者隱藏顯示后刷新界面,key值就不能使用indexPath, 高度緩存對應(yīng)關(guān)系會是錯的, 應(yīng)該使用cell對應(yīng)的界面類型/業(yè)務(wù)類型,否則依然會有抖動問題。

對于每個cell對應(yīng)一個model的情況,我們可以將高度緩存至model中

#pragma mark - 解決動態(tài)cell高度 reloadData刷新抖動的問題

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
     DemoModel *model = self.dataArray[indexPath.row];
     model.esHegiht = cell.frame.size.height;
}

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
     DemoModel *model = self.dataArray[indexPath.row];
     return model.esHegiht?:50; // 為0時最好返回最接近的預(yù)估高度
}

對于所有cell對應(yīng)一個model的情況,比如一些詳情頁,我們可以以cell的類型緩存高度

/**
偽代碼
*/
- (void)buildDataArray {
    // tableView數(shù)據(jù)源推薦使用這種方式 可以擺脫if indexPath.row的判斷,方便維護。
    // 可以不使用枚舉,使用字符串,cell的類名都可以,根據(jù)業(yè)務(wù)。
    self.dataArray = @[@(InfoCellType1),@(InfoCellType2)];
}

#pragma mark - 解決動態(tài)cell高度 reloadData刷新抖動的問題
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    InfoCellType type = [self.dataArray[indexPath.row] integerValue];
    __weak typeof(self) weakSelf = self;
    DemoTableViewCell *cell;
    switch (type) {
        case InfoCellType1:
            cell = [tableView dequeueReusableCellWithIdentifier:@"cellId1" forIndexPath:indexPath];
            break;
        case InfoCellType2:{
            cell = [tableView dequeueReusableCellWithIdentifier:@"cellId2" forIndexPath:indexPath];
        }
            break;
        default:
            break;
    }
   cell.model = self.infoModel;
    return cell;
}

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
 // 取出對應(yīng)的界面類型
  NSNumber *typeNumber = self.dataArray[indexPath.row];
   _estimatedRowHeightCache[typeNumber] = @(cell.frame.size.height);
}

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
   NSNumber *typeNumber = self.dataArray[indexPath.row];
    return [_estimatedRowHeightCache[typeNumber] floatValue] ?:50; // 為0時最好返回最接近的預(yù)估高度
}
2 .返回預(yù)估模糊高度不能返回0,否則會發(fā)生cell不會出現(xiàn)的問題。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對...
    cosWriter閱讀 11,618評論 1 32
  • 我們在上一篇《通過代碼自定義不等高cell》中學(xué)習(xí)了tableView的相關(guān)知識,本文將在上文的基礎(chǔ)上,利用sto...
    啊世ka閱讀 1,637評論 2 7
  • 2017.02.22 可以練習(xí),每當(dāng)這個時候,腦袋就犯困,我這腦袋真是神奇呀,一說讓你做事情,你就犯困,你可不要太...
    Carden閱讀 1,490評論 0 1
  • iOS網(wǎng)絡(luò)架構(gòu)討論梳理整理中。。。 其實如果沒有APIManager這一層是沒法使用delegate的,畢竟多個單...
    yhtang閱讀 5,465評論 1 23
  • 這篇文章可以讓你輕松理解什么是AOP 先說一個Spring是什么吧,大家都是它是一個框架,但框架這個詞對新手有點抽...
    琴匣自鳴閱讀 332評論 0 0

友情鏈接更多精彩內(nèi)容