iOS學習筆記-TableView效能優化篇2

Yang1492955186752發表於2017-12-13

上篇我們講到了tableView是繼承自scrollView,假如cell中有比較多的圖片需要通過網路載入,這時候我們可以利用scrollView的代理來進行網路請求的時機選擇從而減小網路開銷和效能損耗。這是看了一篇關於UIScrollView 實踐經驗後得到的啟發。 首先我們得了解scrollView的幾個常用的代理方法。為了方便理解,特地把方法進行排序,滑動時呼叫順序從上到下

//在手指開始滑動的時候進行呼叫,在滑動過程中可以多次呼叫
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView;
複製程式碼
//只要產生偏移量,就會呼叫這個方法,並且不分程式碼和手勢
- (void)scrollViewDidScroll:(UIScrollView *)scrollView;
複製程式碼
//即將結束拖動的時候呼叫
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset;
複製程式碼
//手指結束拖動的時候呼叫,在滑動過程中可以多次呼叫
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate;
複製程式碼
//手指離開螢幕後,在didEndDragging後呼叫
- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView;
複製程式碼

如下圖

4D7CABDF-A844-42B4-BB74-B3CA8586E993.png
在iOS5以後,scrollView多了一個代理方法- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset。 這個方法能夠在你手手指拖動結束的時候計算出tableView的contentOffset,注意這裡的contentOff是一個指標,這意味我們可以修改這個值,從而設定最終偏移量使滑動看起來更順暢,呃,跑遍了,目前暫時不會用到修改這個指標。我們拿到這個contentOffset後,就可以得到滑動結束後的可視矩形visibleRect的範圍。 另外,這時候呼叫tableViewCell- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath方法時,假如cell中圖片需要網路請求,這時候我們可以先暫時不請求圖片,只需要把imageView的大小確定(通過伺服器傳回來的imageSize)。然後根據CGRect targetRect = CGRectMake(targetContentOffset->x, targetContentOffset->y, scrollView.frame.size.width, scrollView.frame.size.height);獲取到滑動目的地的targetRect。這時候程式碼如下:

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
{
//  NSLog(@"%s",__func__);
CGRect targetRect = CGRectMake(targetContentOffset->x, targetContentOffset->y, scrollView.frame.size.width, scrollView.frame.size.height);
self.targetRect = [NSValue valueWithCGRect:targetRect];
}
複製程式碼

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView這個方法中我們先將self.targetRect設為nil,這時候我們可以根據tableView的visibleCells獲取到當前螢幕中正在顯示的cell,然後先進行判斷後在進行網路請求,那麼如何判斷呢?1.先判斷需要顯示圖片的imageView是否存在與modelArray[indexPath.row]相同的sd_imageURL,這是為了排除cell重用的弊端。2.然後判斷targetRect是否與當前可視的cell的frame有交集,可以利用CGRectIntersectsRect(CGRect rect1, CGRect rect2)進行判斷,假如沒有交集,不需要進行圖片的網路載入。

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{

//    NSLog(@"%s",__func__);
self.targetRect = nil;
[self loadVisibleCell];
}
複製程式碼
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
{
//  NSLog(@"%s",__func__);
CGRect targetRect = CGRectMake(targetContentOffset->x, targetContentOffset->y, scrollView.frame.size.width, scrollView.frame.size.height);
self.targetRect = [NSValue valueWithCGRect:targetRect];
}
複製程式碼
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
//  NSLog(@"%s",__func__);
self.targetRect = nil;
[self loadVisibleCell];
}
複製程式碼
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = @"ImageCell";
HYImageCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
//這裡可以對非圖片的控制元件進行直接顯示,只是把圖片用下面的方法進行載入就行
[self configureCell:cell withIndexPath:indexPath];

return cell;
}
複製程式碼
- (void)configureCell:(HYImageCell *)cell withIndexPath:(NSIndexPath *)indexPath{
Model *model = _modelArray[indexPath.row];
NSURL *targetURL = [NSURL URLWithString:model.hoverURL];

NSLog(@" 111---  %@ ---111",cell.photoView.sd_imageURL );

BOOL shouldLoadImage = YES;

// 根據targetRect的值來判斷是否載入圖片
//targetRect什麼時候有值呢?看前面的代理方法,在willEndDragging的時候我們獲得了targetRect的frame然後在DidEndDecelerating裡我們又清空了targetRect的值
//targetRect有值 && 當前顯示的cell與targetRect不相交,所以不用進行網路請求
//targetRect沒值就進行圖片載入
//因此無論各種手指操作,都能得到想要的效果--快速滑動的時候中間是空白的,只有與targetRect相交的cell圖片才會被顯示出來
if (self.targetRect && !CGRectIntersectsRect([self.targetRect CGRectValue], cellFrame)){
shouldLoadImage = NO;
}
if (shouldLoadImage) {
//圖片載入

}


}
複製程式碼

最後貼上鍊接:https://github.com/Yang9322/ScrollView.git

相關文章