iOS Tableview 緩存池的發(fā)現(xiàn)

項目中出現(xiàn)了一個Bug,之后在解這個Bug 的過程中發(fā)現(xiàn)了一些有趣的東西,所以今天把這個記錄下來。

  • 通過這個Bug,調(diào)試之后知道,tableview 的調(diào)用順序
    1.調(diào)用 heightForRow 方法來確定 scrollview 的 contentSize,
    2.調(diào)用 cellForRow 方法來確定 cell 的內(nèi)容是什么
    3.再次調(diào)用 heightForRow 方法確定最終的 cell 顯示的高度和內(nèi)容。

也就是說在第三次調(diào)用之前,我們寫的 cell 的高度只是一個默認值,這時的 height 值并不能作為一個參考值使用

  • 項目中的 bug 情況是由以下代碼引起的
[self.tableview reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationNone];

過程就不多說,直接說結(jié)果
以上方法使用的緩存池和以下方法使用的緩存池不是同一個

[self.tableview reloadData]

代碼邏輯是這樣的,先有一個數(shù)據(jù)源,改變數(shù)據(jù)源之后只更新當前section

self.dataArray = @[@[@"中國", @"韓國"],@[ @"美國", @"德國"]].mutableCopy;
[self.tableview reloadData];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

     self.dataArray[0] = @[@"橘子",@"柚子"];
     [self.tableview reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationNone];
});

驗證如下

未調(diào)用 reloadSections 的時候打印 self.tableview.subviews 是這樣的
第一次打印

調(diào)用 reloadSections 的之后打印 self.tableview.subviews 是這樣的
reloadSections調(diào)用之后

可以看到調(diào)用之后 tableview 的緩存池里面的 cell 多了兩個。

  • 改變代碼,驗證一下
self.dataArray = @[@[@"中國", @"韓國"],@[ @"美國", @"德國"]].mutableCopy;
[self.tableview reloadData];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

     self.dataArray[0] = @[@"橘子",@"柚子"];
    [self.tableview reloadData];
});

上面代碼之后的打印結(jié)果如下圖:

要是這么寫代碼

    self.dataArray = @[@[@"中國", @"韓國"],@[ @"美國", @"德國"]].mutableCopy;
    [self.tableview reloadData];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(6 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        self.dataArray[1] = @[@"橙子",@"栗子"];
        [self.tableview reloadSections:[NSIndexSet indexSetWithIndex:1] withRowAnimation:UITableViewRowAnimationNone];
        self.dataArray[0] = @[@"橘子",@"柚子"];
        [self.tableview reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationNone];
    });

打印的結(jié)果就是這樣了

我猜想 reloadSections 方法是異步進行的
驗證如下

   self.dataArray = @[@[@"中國", @"韓國"],@[ @"美國", @"德國"]].mutableCopy;
    [self.tableview reloadData];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(6 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        self.dataArray[1] = @[@"橙子",@"栗子"];
        [self.tableview reloadSections:[NSIndexSet indexSetWithIndex:1] withRowAnimation:UITableViewRowAnimationNone];
    });
  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        
     self.dataArray[0] = @[@"橘子",@"柚子"];
    [self.tableview reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationNone];
    });
   
    

結(jié)果如下圖

可以驗證猜想正確

要是這么寫

    self.dataArray = @[@[@"中國", @"韓國"],@[ @"美國", @"德國"]].mutableCopy;
    [self.tableview reloadData];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        
        self.dataArray[0] = @[@"橘子",@"柚子"];
        [self.tableview reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationNone];
        self.dataArray[1] = @[@"橙子",@"栗子"];
        [self.tableview reloadSections:[NSIndexSet indexSetWithIndex:1] withRowAnimation:UITableViewRowAnimationNone];
    });
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(6 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        
        self.dataArray = @[@[@"iPhone", @"iPod"],@[ @"iMac", @"iPad"]].mutableCopy;
        [self.tableview reloadData];
    });

debug 圖片可以看出來reloadData 方法是首先復用 reloadSections 的緩存 cell的

最后想說的是,出屏 cell 的緩存池復用是不存在這種差異化的。

3 月 27 日更新:
經(jīng)過查看 reloadSections 的官方文檔對此方法的解釋,因為沒有 OC 的源碼,只能對上面的現(xiàn)象做一些合理的猜測。

  • reloadSections 方法是一定會 new cell 的
  • dequeue 方法會優(yōu)先拿屏幕上顯示的 cell 來復用。
  • 使用 reloadSections 方法在 new 完之后把原先屏幕上的 cell 擠入了緩存池,這些 cell 在 tableview 未滑動出屏之前都不會被使用
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

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

  • ## iOS常用問題總結(jié)#### iOS基礎知識回顧##### 1、為什么說Objective-C是一門動態(tài)的語言...
    蟬始鳴閱讀 517評論 0 3
  • 概述在iOS開發(fā)中UITableView可以說是使用最廣泛的控件,我們平時使用的軟件中到處都可以看到它的影子,類似...
    liudhkk閱讀 9,289評論 3 38
  • 2015年的端午節(jié)放假后上班第一天,組織正式談話調(diào)整工作。整整兩年的時間,依然記得在一號會議室談話的場景、依然記得...
    武春麗閱讀 541評論 3 1
  • 走了?真走了? 你這家伙,你著什么急呀,,, 9月份在一次喜酒上遇到,還一起噴了一陣子呢。 你大贊我寫的《電影舊事...
    老慕_sy閱讀 1,554評論 0 4
  • 你羨慕別人的時候,別人也在羨慕你 我從來沒有想過,有一天,我可以進入我曾經(jīng)無比羨慕過的行業(yè)。 坐在干凈明亮,纖塵不...
    麥芽余魚閱讀 1,086評論 3 1

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