App 測試時 一次偶然的 UITableView 崩潰調(diào)試過程

最近在做一款醫(yī)療類的app,有一個 feed 流頁面(醫(yī)生列表)涉及到數(shù)據(jù)源刪除插入操作。

相關(guān)操作:用戶如果點擊了不喜歡某個醫(yī)生的按鈕,就會把這個醫(yī)生從他的醫(yī)生列表刪除。

調(diào)試信息:

Assertion failure in -[UITableView _endCellAnimationsWithContext:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit/UIKit-3694.4.18/UITableView.m:1950

* Terminating app due to uncaught exception ‘NSInternalInconsistencyException’, reason: ‘Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (19) must be equal to the number of rows contained in that section before the update (21), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).’

崩潰主線程函數(shù)幀棧:

thread

多次操作復(fù)現(xiàn)問題:

點擊不喜歡按鈕,然后刷新醫(yī)生列表,點擊喜歡按鈕,然后刷新列表。發(fā)現(xiàn)并不是每次都會出現(xiàn)崩潰,有時出現(xiàn),有時又不會出現(xiàn)。

分析問題:

從上面的信息,第一時間想到的就是:table view 中顯示的數(shù)據(jù)和其數(shù)據(jù)源不一致導致的。
刪除醫(yī)生列表時只使用了下面兩句代碼:

[self.listModel.dataList removeObjectAtIndex:indexPath.row];
[self.listView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];

先刪除數(shù)據(jù)源中的某一條數(shù)據(jù),再使用 -[UITableView deleteRowsAtIndexPaths:withRowAnimation:] 將數(shù)據(jù)源同步到 table view 上。按理說這樣的操作并不會導致任何問題,但為什么這里執(zhí)行到 -[UITableView deleteRowsAtIndexPaths:withRowAnimation:] 時會崩潰呢?

我第一反應(yīng)覺得應(yīng)該多線程異步操作導致的問題,認為是在執(zhí)行刪除操作時其它地方在非主線程也對該列表進行了寫操作。于是在刪除數(shù)據(jù)源中的數(shù)據(jù)這行代碼前后加了打印信息:

NSLog(@"count0: %ld", self.listModel.dataList.count);
NSLog(@"count1: %ld", [self.listView.dataSource tableView:self.listView numberOfRowsInSection:0]);
[self.listModel.dataList removeObjectAtIndex:indexPath.row];
NSLog(@"count2: %ld", self.listModel.dataList.count);
NSLog(@"count3: %ld", [self.listView.dataSource tableView:self.listView numberOfRowsInSection:0]);

打印信息:

count0: 23 
count1: 23
count2: 22 
count3: 22

這樣看起來也沒問題,也就是說很可能不是多線程引起的問題。

解決問題:

我就想到了很可能是有其它地方更改了數(shù)據(jù)源,但是并沒有及時更新UI 界面導致的。

經(jīng)過查找,確實發(fā)現(xiàn)有一行代碼:

[self.listModel.dataList removeObject:object];

但并沒有通過 reload/delete/insert 等方法對 table view 進行更新,導致 -[UITableView numberOfRowsInSection:] 方法返回的數(shù)目還是對數(shù)據(jù)源進行刪除操作之前的數(shù)目。

因此只要在該行代碼之后利用 reload/delete/insert 等方法對 table view 進行更新后,下一次在其他地方執(zhí)行 reload/delete/insert 操作后也就不再崩潰了。

參考鏈接:

https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/TableView_iPhone/ManageInsertDeleteRow/ManageInsertDeleteRow.html#//apple_ref/doc/uid/TP40007451-CH10-SW1

最后編輯于
?著作權(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)容

  • 社會閱歷淺的人,當冒犯發(fā)生時,會第一時間追隨原始情緒進行反擊,然后這樣的反擊多半沒有深入思考,并缺乏策略,最終的結(jié)...
    天空的羈絆閱讀 717評論 0 0
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,753評論 18 399
  • 多才多藝
    葉囡閱讀 258評論 0 0

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