更新提示:
【2018年11月20日更新】
經過放置在項目中運行發現,如果在快速滾動tableview的時候會在下面這行代碼中崩潰(慢慢的滾動是沒關系的~):
CGFloat cellHeight = [tableView rectForRowAtIndexPath:[NSIndexPath indexPathForRow:(indexPath.row - 1) inSection:indexPath.section]].size.height;
提示的error原因是,超出數組的范圍進行訪問。原因,后面有時間會詳細說明更新進來,大致的原因就是利用rectForRowIndexPath方法去取cell的時候,從展示在界面上的第一個完整的cell開始作為下標為0的cell。比如,一個界面中可以存放4個cell,第5個cell將要展示的時候,會在界面中去取下標為3的cell。有一點需要插播一條,就是在第5個cell還沒有漏出來之前,系統就會去調用tableview的cellForRowAtIndexPath協議方法了,這就是為什么你慢慢的滾動tableview是沒有關系的。如果快速滾動的話,雖然系統也是在第5個cell還沒有漏出來之前就去調用那個協議方法了,但是等到運行到rectForRowIndexPath方法的時候,第1個cell就已經被頂出tableview的可視區域了,這個時候下標為0的cell就是從開始的第2個cell開始了(第一個cell在屏幕中的部分並不是完整的了),所以就會拋出異常。
暫時先把“indexPath.row - 1”的“-1”改為“-2”暫且應付。
因為如果tableview的可視范圍最多只能同時容納2個完整的cell的話,使用“-2”就會往前超域訪問數組;如果最多只能同時容納1個完整的cell的話,使用“-1”也會往前超域訪問數組;如果連一個完整的cell都容納不下,那么這個方法就根本行不通了。(很尷尬~)
問題背景:
使用MJRefresh一直都很方便,適配到iOS11以后,tableView上拉加載更多數據動畫結束后,出現tableView跳動、閃動的現象。
通過瀏覽Github上的MJRefresh的Issues后發現,很多人都遇到了這個問題。而且,一般遇到這個問題的都是使用自動化布局來自動約束Cell高度的同學。如果將Cell是通過tableView的rowHeight屬性或者對應的協議方法給定的,就不出遇上這個問題。
分析問題:
為了實現Cell的高度自適應,需要做三步:
1、不要設置rowHeight、不要重寫設置rowHeight的協議方法
2、在搭建Cell的UI時,讓最后一個控件的bottom等於cell.contentView.mas_bottom(這里用masonry舉例)
3、設置tableView的下面兩個屬性:
self.estimatedRowHeight = 44; self.rowHeight = UITableViewAutomaticDimension;
有同學說,走回以前“根據內容計算好cell的高度”的方式,很定是不合適的,與蘋果推崇的AutoLayout相違背。
所以使用上面的高度自適應方式,是沒錯的,錯就錯在
estimatedRowHeight
這個屬性的設置。
如果通過高度自適應計算出來Cell的真實高度與給出的估算高度相差太大,很定出現view渲染過程的異常。
解決方式:
根據上面的分析,本ID采用的方式是加載cell時,將上一個cell對象的高度設置為下一個即將出現的cell的預估高度。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row > 1) { CGFloat cellHeight = [tableView rectForRowAtIndexPath:[NSIndexPath indexPathForRow:(indexPath.row - 1) inSection:indexPath.section]].size.height; self.estimatedRowHeight = cellHeight; } //。。。你之前的代碼 return cell; }