国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

iOS中關于列表滾動流暢的一些探討

移動開發 iOS
近些年,App 越來越推崇體驗至上,隨隨便便亂寫一通的話已經很難讓用戶買帳了,順滑的列表便是其中很重要的一點。如果一個 App 的頁面滾動起來總是卡頓卡頓的,輕則被當作反面教材來吐槽或者襯托“我們的 App balabala…”,重則直接卸載。正好最近在優化這一塊兒,總結記錄下。

近些年,App 越來越推崇體驗至上,隨隨便便亂寫一通的話已經很難讓用戶買帳了,順滑的列表便是其中很重要的一點。如果一個 App 的頁面滾動起來總是卡頓卡頓的,輕則被當作反面教材來吐槽或者襯托“我們的 App balabala…”,重則直接卸載。正好最近在優化這一塊兒,總結記錄下。

如果說有什么好的博客文章推薦,ibireme 的 iOS 保持界面流暢的技巧 這篇堪稱業界毒瘤,墻裂推薦反復閱讀。這篇文章中講解了很多的優化點,我自己總結了下收益***的兩個優化點:

  • 避免重復多次計算 cell 行高
  • 文本異步渲染

iOS 中關于列表滾動流暢的一些探討

大家可以看看上面這張圖的對比分析,數據是 iPhone6 的機子用 instruments 抓的,左邊的是用 Auto Layout 繪制界面的數據分析,正常如果想平滑滾動的話,fps 至少需要穩定在 55 左右,我們可以發現,在沒有緩存行高和異步渲染的情況下 fps 是***的,可以說是比較卡頓了,至少是能肉眼感覺出來,能滿足平滑滾動要求的也只有在緩存行高且異步渲染的情況下;右邊的是沒用 Auto Layout 直接用 frame 來繪制界面的數據分析,可以發現即使沒有異步渲染,也能勉強滿足平滑滾動的要求,如果開啟異步渲染的話,可以說是相當的絲滑了。

避免重復多次計算 cell 行高

TableView 行高計算可以說是個老生常談的問題了, heightForRowAtIndexPath: 是個調用相當頻繁的方法,在里面做過多的事情難免會造成卡頓。 在 iOS 8 中,我們可以通過設置下面兩個屬性來很輕松的實現高度自適應: 

  1. self.tableView.estimatedRowHeight = 88; 
  2. self.tableView.rowHeight = UITableViewAutomaticDimension; 

 雖然很方便,不過如果你的頁面對性能有一定要求,建議不要這么做,具體可以看看 sunnyxx 的 優化UITableViewCell高度計算的那些事 。文中針對 Auto Layout,提供了個 cell 行高的緩存庫 UITableView-FDTemplateLayoutCell ,可以很好的幫助我們避免 cell 行高多次計算的問題。

如果不使用 Auto Layout,我們可以在請求完拿到數據后提前計算好頁面個個控件的 frame 和 cell 高度,并且緩存在內存中,用的時候直接在 heightForRowAtIndexPath: 取出計算好的值就行,大概流程如下:

模擬請求數據回調: 

  1. - (void)viewDidLoad { 
  2.     [super viewDidLoad]; 
  3.      
  4.     [self buildTestDataThen:^(NSMutableArray <FDFeedEntity *> *entities) { 
  5.         self.data = @[].mutableCopy; 
  6.         @autoreleasepool { 
  7.             for (FDFeedEntity *entity in entities) { 
  8.                 FrameModel *frameModel = [FrameModel new]; 
  9.                 frameModel.entity = entity; 
  10.                 [self.data addObject:frameModel]; 
  11.             } 
  12.         } 
  13.         [self.tvFeed reloadData]; 
  14.     }]; 

一個簡單計算 frame 、cell 行高方式: 

  1. //FrameModel.h 
  2.  
  3. @interface FrameModel : NSObject 
  4.  
  5. @property (assign, nonatomic, readonly) CGRect titleFrame; 
  6. @property (assign, nonatomic, readonly) CGFloat cellHeight; 
  7. @property (strong, nonatomic) FDFeedEntity *entity; 
  8.  
  9. @end 
  10.  
  11. //FrameModel.m 
  12.  
  13. @implementation FrameModel 
  14.  
  15. - (void)setEntity:(FDFeedEntity *)entity { 
  16.     if (!entity) return
  17.      
  18.     _entity = entity; 
  19.      
  20.     CGFloat maxLayout = ([UIScreen mainScreen].bounds.size.width - 20.f); 
  21.     CGFloat bottom = 4.f; 
  22.      
  23.     //title 
  24.     CGFloat titleX = 10.f; 
  25.     CGFloat titleY = 10.f; 
  26.     CGSize titleSize = [entity.title boundingRectWithSize:CGSizeMake(maxLayout, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName : Font(16.f)} context:nil].size
  27.     _titleFrame = CGRectMake(titleX, titleY, titleSize.width, titleSize.height); 
  28.      
  29.     //cell Height 
  30.     _cellHeight = (CGRectGetMaxY(_titleFrame) + bottom); 
  31.  
  32. @end 

行高取值: 

  1. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
  2.     FrameFeedCell *cell = [tableView dequeueReusableCellWithIdentifier:FrameFeedCellIdentifier forIndexPath:indexPath]; 
  3.     FrameModel *frameModel = self.data[indexPath.row]; 
  4.     cell.model = frameModel; 
  5.     return cell; 
  6.  
  7. - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 
  8.     FrameModel *frameModel = self.data[indexPath.row]; 
  9.     return frameModel.cellHeight; 

控件賦值: 

  1. - (void)setModel:(FrameModel *)model { 
  2.     if (!model) return
  3.      
  4.     _model = model; 
  5.      
  6.     FDFeedEntity *entity = model.entity; 
  7.      
  8.     self.titleLabel.frame = model.titleFrame; 
  9.     self.titleLabel.text = entity.title; 

優缺點

緩存行高方式有現成的庫簡單方便,雖然 UITableView-FDTemplateLayoutCell 已經處理的很好了,但是 Auto Layout 對性能還是會有部分消耗;手動計算 frame 方式所有的位置都需要計算,比較麻煩,而且在數據量很大的情況下,大量的計算對數據展示時間會有部分影響,相應的回報就是性能會更好一些。

文本異步渲染

當顯示大量文本時,CPU 的壓力會非常大。對此解決方案只有一個,那就是自定義文本控件,用 TextKit 或***層的 CoreText 對文本異步繪制。盡管這實現起來非常麻煩,但其帶來的優勢也非常大,CoreText 對象創建好后,能直接獲取文本的寬高等信息,避免了多次計算(調整 UILabel 大小時算一遍、UILabel 繪制時內部再算一遍);CoreText 對象占用內存較少,可以緩存下來以備稍后多次渲染。

幸運的是,想支持文本異步渲染也有現成的庫 YYText ,下面來講講如何搭配它***程度滿足我們如絲般順滑的需求:

Frame 搭配異步渲染

基本思路和計算 frame 類似,只不過把系統的 boundingRectWithSize: 、 sizeWithAttributes: 換成 YYText 中的方法:

配置 frame model: 

  1. //FrameYYModel.h 
  2.  
  3. @interface FrameYYModel : NSObject 
  4.  
  5. @property (assign, nonatomic, readonly) CGRect titleFrame; 
  6. @property (strong, nonatomic, readonly) YYTextLayout *titleLayout; 
  7.  
  8. @property (assign, nonatomic, readonly) CGFloat cellHeight; 
  9.  
  10. @property (strong, nonatomic) FDFeedEntity *entity; 
  11.  
  12. @end 
  13.  
  14. //FrameYYModel.m 
  15.  
  16. @implementation FrameYYModel 
  17.  
  18. - (void)setEntity:(FDFeedEntity *)entity { 
  19.     if (!entity) return
  20.      
  21.     _entity = entity; 
  22.      
  23.     CGFloat maxLayout = ([UIScreen mainScreen].bounds.size.width - 20.f); 
  24.     CGFloat space = 10.f; 
  25.     CGFloat bottom = 4.f; 
  26.      
  27.     //title 
  28.     NSMutableAttributedString *title = [[NSMutableAttributedString alloc] initWithString:entity.title]; 
  29.     title.yy_font = Font(16.f); 
  30.     title.yy_color = [UIColor blackColor]; 
  31.      
  32.     YYTextContainer *titleContainer = [YYTextContainer containerWithSize:CGSizeMake(maxLayout, CGFLOAT_MAX)]; 
  33.     _titleLayout = [YYTextLayout layoutWithContainer:titleContainer text:title]; 
  34.      
  35.     CGFloat titleX = 10.f; 
  36.     CGFloat titleY = 10.f; 
  37.     CGSize titleSize = _titleLayout.textBoundingSize; 
  38.     _titleFrame = (CGRect){titleX,titleY,CGSizeMake(titleSize.width, titleSize.height)}; 
  39.      
  40.     //cell Height 
  41.     _cellHeight = (CGRectGetMaxY(_titleFrame) + bottom); 
  42.  
  43. @end 

對比上面 frame,可以發現多了個 YYTextLayout 屬性,這個屬性可以提前配置文本的特性,包括 font 、 textColor 以及行數、行間距、內間距等等,好處就是可以把一些邏輯提前處理好,比如根據接口字段,動態配置字體顏色,字號等,如果用 Auto Layout,這部分邏輯則不可避免的需要寫在 cellForRowAtIndexPath: 方法中。

UITableViewCell 處理 : 

  1. - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { 
  2.     self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 
  3.     if (!self) return nil; 
  4.    
  5.     YYLabel *title = [YYLabel new]; 
  6.     title.displaysAsynchronously = YES; //開啟異步渲染 
  7.     title.ignoreCommonProperties = YES; //忽略屬性 
  8.     title.layer.borderColor = [UIColor brownColor].CGColor; 
  9.     title.layer.cornerRadius = 1.f; 
  10.     title.layer.borderWidth = 1.f; 
  11.     [self.contentView addSubview:_titleLabel = title]; 
  12.    
  13.     return self; 

賦值: 

  1. - (void)setModel:(FrameYYModel *)model { 
  2.     if (!model) return
  3.     _model = model; 
  4.      
  5.     self.titleLabel.frame = model.titleFrame; 
  6.     self.titleLabel.textLayout = model.titleLayout; //直接取 YYTextLayout 

 Auto Layout 搭配異步渲染

YYText 非常友好,同樣支持 xib,YYText 繼承自 UIView ,正常的在 xib 中配置約束就行了,需要注意的一點是,多行文本的情況下需要設置***換行寬: 

  1. CGFloat maxLayout = [UIScreen mainScreen].bounds.size.width - 20.f; 
  2. self.titleLabel.preferredMaxLayoutWidth = maxLayout; 
  3. self.subTitleLabel.preferredMaxLayoutWidth = maxLayout; 
  4. self.contentLabel.preferredMaxLayoutWidth = maxLayout; 

 優缺點

YYText 的異步渲染能極大程度的提高列表流暢度,真正達到如絲般順滑,但是在開啟異步時,刷新列表會有閃爍情況,不知道算不算 bug,最近也看到作者回歸了,相信這個庫會越來越好,畢竟 真●大神!

其它

列表中如果存在很多系統設置的圓角頁面導致卡頓: 

  1. label.layer.cornerRadius = 5.f; 
  2. label.clipsToBounds = YES; 

 其實據我觀察,只要當前屏幕內只要設置圓角的控件個數不要太多(大概十幾個算個零界點),就不會引起卡頓。

還有就是只要不設置 clipsToBounds 不管多少個,都不會卡頓,比如你需要圓角的控件是白色背景色的,然后它的父控件也是白色背景色的,而且沒有點擊后高亮的,就沒必要 clipsToBounds 了。

總結

YYText 和 UITableView-FDTemplateLayoutCell 搭配可以很大程度的提高列表流暢度,如果時間比較緊迫,可以直接采取 Auto Layout + UITableView-FDTemplateLayoutCell + YYText 方式;如果列表中文本不包含富文本,僅僅顯示文字,又不想引入這兩個庫,可以使用系統方式提前計算 Frame;如果想***程度的流暢度,就需要使用 提前計算 Frame + YYText,具體大家根據自己情況選擇合適的方案就行。

責任編輯:未麗燕 來源: ifelseboyxx's Blog
相關推薦

2017-02-20 16:28:30

DCISDN-WAN傳輸網絡

2022-01-12 08:30:55

結構體指針STM32

2009-03-13 09:31:03

.NET整合分布式應用

2011-07-13 09:13:56

Android設計

2009-07-02 10:52:30

JavaBean規范

2009-11-25 09:23:47

PHP引用&符號

2013-04-07 10:40:55

前端框架前端

2009-06-18 09:51:25

Java繼承

2022-11-09 19:02:10

Linux

2023-02-10 09:46:04

bash腳本變量

2012-09-25 10:03:56

JavaJava封面Java開發

2012-04-19 10:06:55

微軟Windows 8 E

2022-04-14 10:22:44

故事卡業務

2020-09-28 06:45:42

故障復盤修復

2017-12-21 07:54:07

2015-12-04 10:04:53

2009-06-04 16:28:43

EJB常見問題

2011-03-11 09:27:11

Java性能監控

2020-04-10 08:50:37

Shell腳本循環

2020-05-19 14:35:42

Shell腳本循環
點贊
收藏

51CTO技術棧公眾號

日韩欧美一区二区三区在线| 2020av在线| 成人丝袜高跟foot| 日本人妖在线| 国产91久久婷婷一区二区| 国产一区不卡视频| www欧美在线观看| 精品少妇在线视频| 久久精品综合网| 亚洲在线视频观看| 99精品视频在线| 成人在线免费高清视频| 欧美日本精品一区二区三区| 免费精品一区二区三区在线观看| 91亚洲永久免费精品| 成人性色生活片| 深夜视频在线免费| 欧美—级a级欧美特级ar全黄| 国产精品一二三在| www.av在线播放| 国产精品爽爽ⅴa在线观看| 国产日韩亚洲欧美综合| 国产激情久久| 久久99久久久久久| 日韩一区二区免费在线观看| 国产欧美大片| 97久久精品人人澡人人爽缅北| 久久狠狠一本精品综合网| yiren22亚洲综合伊人22| 免费一区二区三区在在线视频| 久久综合久久久久88| 成年人在线看| 91av在线国产| 成人性生交大片免费看视频在线 | 黄色亚洲网站| 国产色综合一区二区三区| 日本在线免费| 国产精品日韩欧美综合| 91性感美女视频| 俺来俺也去www色在线观看| 91亚洲精品久久久久久久久久久久| 99r国产精品| 天天免费亚洲黑人免费| 日韩精品久久一区| 欧美电影影音先锋| 亚洲欧美日韩视频二区| 草碰在线视频| 91久久久久久国产精品| 一区二区三区在线影院| 日韩欧美少妇| 中文字幕在线中文字幕日亚韩一区| 欧美电影影音先锋| 老色鬼久久亚洲一区二区| 日本电影在线观看网站| 国产高清精品一区二区| 欧美视频在线观看免费| 激情六月综合| av福利导福航大全在线| 黄色录像特级片| 日韩在线观看免费全| 国产精品欧美一区喷水| 日韩高清影视在线观看| 日韩精品一二| 精品乱码一区| 国产一区二区三区在线播放免费观看 | 午夜精品久久久久久久久| 欧美日本在线| 麻豆视频在线观看免费网站黄| 中文字幕超清在线免费观看| 欧美日韩一区国产| 国产精品996| 国产一区日韩| 99爱在线视频| 视色视频在线观看| 99在线热播| 中文字幕亚洲字幕| 一区二区三区日韩欧美精品| 日韩午夜黄色| 粉嫩精品导航导航| 色呦呦在线视频| av一级毛片| 51xx午夜影福利| 成人字幕网zmw| 亚洲人成网在线播放| 一区二区高清视频在线观看| 久久99国产精品免费| 秋霞欧美视频| 国产一区二区| 国产乱码精品一区二三赶尸艳谈| 91黑丝在线| 国产一二三在线视频| 国产精品二区在线观看| 久久久久久美女| 亚洲精品国产综合区久久久久久久 | 国产无限制自拍| 欧美一区二区三区电影在线观看 | 精品一区二区三区日韩| 亚洲国产1区| 精品在线91| 精品一区91| 欧美激情福利| 成人福利av| 最新欧美色图| 色呦呦网站在线观看| 成人精品一区二区三区| 日本免费在线精品| 久久久爽爽爽美女图片| 一区二区欧美久久| 亚洲人线精品午夜| 精品国产一区二区三区久久久蜜月| 91福利在线播放| 午夜久久久影院| 午夜精品一区二区三区免费视频 | **三级三级97片毛片| 免费日韩中文字幕| 成人亚洲在线观看| 一级特黄视频| 99精品在线观看视频| 中文字幕综合一区| 欧美刺激午夜性久久久久久久| 欧美日韩国产丝袜另类| 亚洲国产综合91精品麻豆| 国产免费成人在线视频| 久久精品人人做| 日韩久久一区二区| 亚洲h动漫在线| 色婷婷精品久久二区二区蜜臂av| 欧美午夜影院一区| 黄色春季福利在线看| 免费看污污网站| 欧美一级特黄a| 中文字幕视频在线观看| 男同在线观看| 羞羞网站在线免费观看| 在线免费看h| 成人自拍视频| 激情婷婷综合| 在线综合欧美| 国产一区三区三区| 久久久久九九视频| 亚洲黄色录像片| 欧美人体做爰大胆视频| 欧美刺激午夜性久久久久久久| 国产小视频国产精品| 久久久久国产精品免费| 精品国产一区二区三区麻豆免费观看完整版 | 可以看美女隐私的网站| 日韩激情av在线免费观看| 欧美精品制服第一页| 51国产成人精品午夜福中文下载 | 久久国内精品自在自线400部| 国产综合色精品一区二区三区| 国产欧美精品一区二区三区四区 | 国产精品三级a三级三级午夜| 成人影院在线看| 57pao国产一区二区| 久久国产福利国产秒拍| 亚洲高清免费一级二级三级| 亚洲色图偷窥自拍| 欧美裸体网站| 国内福利写真片视频在线| fc2ppv国产精品久久| 欧美电影免费| 国产日韩欧美亚洲| 亚洲欧美日本伦理| 日本va欧美va欧美va精品| 亚洲不卡在线观看| 国产精品成人国产乱一区| 国产精品自拍合集| 亚洲区欧洲区| 亚洲福利免费| 欧美三级电影一区| 91精品国产一区二区三区动漫 | 午夜精品毛片| 1024成人网色www| 欧美在线不卡区| 欧美三级午夜理伦三级| 91精品福利观看| 成人午夜免费电影| 一区二区三区高清国产| 免费在线精品视频| 日本h片久久| 久久综合九色综合97婷婷女人| 精品国产百合女同互慰| 性欧美精品一区二区三区在线播放| 国产youjizz在线| 免费日韩一区二区| 精品免费视频一区二区| 欧洲久久久久久| 色吊丝在线永久观看最新版本| 激情五月色综合国产精品| 五月天网站亚洲| 成人黄色在线观看| 成年人视频网站在线| 蜜臀久久99精品久久久久宅男 | 涩涩涩在线视频| 9人人澡人人爽人人精品| 久久中国妇女中文字幕| jizzjizz亚洲中国少妇| 久久久久国内|