這個(gè)問題在我做火柴盒用戶crash分析的時(shí)候,曾經(jīng)困擾我挺久的,需要較大的用戶量,才能發(fā)現(xiàn)這個(gè)crash,解決之后,也不知道怎么敘述出來,恰好最近好幾個(gè)人都遇到這個(gè)問題了,我在群里裝完逼之后,素顏大大簡(jiǎn)單粗暴的給這篇博客起了這個(gè)名字,于是就有了這篇博客。
那么,先來個(gè)我畫的示意圖:
正文來啦:
一般我們的刷新控件,和網(wǎng)絡(luò)請(qǐng)求數(shù)據(jù)源,刷新界面,是分開來封裝的,而刷新控件往往都會(huì)有個(gè)動(dòng)畫,約0.3-0.5s位移向上消失。看著上圖,如果刷新控件向上運(yùn)動(dòng)過程中,紫色cell的數(shù)據(jù)源已經(jīng)被更新,木有了,紫色cell繪制的時(shí)候,就會(huì)出現(xiàn)數(shù)組越界的問題。
出現(xiàn)問題的代碼大概長(zhǎng)這樣:
//網(wǎng)絡(luò)請(qǐng)求結(jié)束后,dataArrary已經(jīng)改變后:
[self.tableView.header endRefreshing];//刷新控件恢復(fù)
[self.tableView reloadData];//重繪tableView
最初我的解決方法是:
[self.tableView reloadData];//重繪tableView
// 主線程延遲執(zhí)行:
double delayInSeconds = 0.1f;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[self.tableView.header endRefreshing];//刷新控件恢復(fù)
});
而在昨天和素顏大大討論之后,我今天測(cè)試的時(shí)候發(fā)現(xiàn),reloadData這個(gè)方法,調(diào)用dataSource的時(shí)候是同步的,而delegate是異步的。
所以最終解決方法其實(shí)很簡(jiǎn)單了,先reloadData,再取消刷新控件:
[self.tableView reloadData];//重繪tableView
[self.tableView.header endRefreshing];//刷新控件恢復(fù)
引申一下:
其實(shí)在看sunny的UITableView-FDTemplateLayoutCell這個(gè)的時(shí)候,應(yīng)該就能發(fā)現(xiàn)reloadData調(diào)用dataSource的時(shí)候是同步的,為此這個(gè)庫(kù)做了cell高度的緩存,保證了tableview reloadData時(shí)的流暢。
引申第二下:
經(jīng)過素顏大大提醒,MJRefresh對(duì)endRefreshing方法采用了0.1秒延時(shí):
#pragma mark - 公共方法
- (void)endRefreshing
{
if ([self.scrollView isKindOfClass:[UICollectionView class]]) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[super endRefreshing];
});
} else {
[super endRefreshing];
}
}
這樣處理面對(duì)固定高度的cell,不會(huì)產(chǎn)生問題,但是,如果高度需要非常復(fù)雜的計(jì)算,或者是xib的高度獲取,線程block時(shí)間要長(zhǎng)于0.1s,仍然會(huì)出現(xiàn)問題。
寫在最后:
技術(shù)這種東西,真是越研究,越發(fā)現(xiàn)自己懂得太少,很多東西看過,就忘了,最簡(jiǎn)單的東西,也需要融會(huì)貫通。現(xiàn)在看看我之前解決本文問題的延時(shí)辦法,真是蠢哭了。。
寫代碼的時(shí)候,實(shí)現(xiàn)效果是最低級(jí)的,更多時(shí)間要在想,為什么這么做,有沒有更好的方法,還有其他的優(yōu)化空間么?與大家共勉。
簡(jiǎn)書已經(jīng)棄用,歡迎移步我的小專欄:
https://xiaozhuanlan.com/dahuihuiiOS