在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

您好,歡迎來電子發燒友網! ,新用戶?[免費注冊]

您的位置:電子發燒友網>源碼下載>通訊/手機編程>

如何讓ios的界面流暢不卡頓

大?。?/span>0.2 MB 人氣: 2017-09-25 需要積分:2

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

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

避免重復多次計算 cell 行高

文本異步渲染

如何讓ios的界面流暢不卡頓

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

避免重復多次計算 cell 行高

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

1

2

self.tableView.estimatedRowHeight = 88;

self.tableView.rowHeight = UITableViewAutomaticDimension;

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

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

模擬請求數據回調:

- (void)viewDidLoad {

[ super viewDidLoad];

[self buildTestDataThen:^(NSMutableArray 《fdfeedentity *》 *entities) {

self.data = @[].mutableCopy;

@autoreleasepool {

for (FDFeedEntity *entity in entities) {

FrameModel *frameModel = [FrameModel new ];

frameModel.entity = entity;

[self.data addObject:frameModel];

}

}

[self.tvFeed reloadData];

}];

}《/fdfeedentity *》

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

//FrameModel.h

@interface FrameModel : NSObject

@property (assign, nonatomic, readonly) CGRect titleFrame;

@property (assign, nonatomic, readonly) CGFloat cellHeight;

@property (strong, nonatomic) FDFeedEntity *entity;

@end

//FrameModel.m

@implementation FrameModel

- (void)setEntity:(FDFeedEntity *)entity {

if (!entity) return ;

_entity = entity;

CGFloat maxLayout = ([UIScreen mainScreen].bounds.size.width - 20.f);

CGFloat bottom = 4.f;

//title

CGFloat titleX = 10.f;

CGFloat titleY = 10.f;

CGSize titleSize = [entity.title boundingRectWithSize:CGSizeMake(maxLayout, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName : Font(16.f)} context:nil].size;

_titleFrame = CGRectMake(titleX, titleY, titleSize.width, titleSize.height);

//cell Height

_cellHeight = (CGRectGetMaxY(_titleFrame) + bottom);

}

@end

行高取值:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

FrameFeedCell *cell = [tableView dequeueReusableCellWithIdentifier:FrameFeedCellIdentifier forIndexPath:indexPath];

FrameModel *frameModel = self.data[indexPath.row];

cell.model = frameModel;

return cell;

}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

FrameModel *frameModel = self.data[indexPath.row];

return frameModel.cellHeight;

}

控件賦值:

- (void)setModel:(FrameModel *)model {

if (!model) return ;

_model = model;

FDFeedEntity *entity = model.entity;

self.titleLabel.frame = model.titleFrame;

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:

//FrameYYModel.h

@interface FrameYYModel : NSObject

@property (assign, nonatomic, readonly) CGRect titleFrame;

@property (strong, nonatomic, readonly) YYTextLayout *titleLayout;

@property (assign, nonatomic, readonly) CGFloat cellHeight;

@property (strong, nonatomic) FDFeedEntity *entity;

@end

//FrameYYModel.m

@implementation FrameYYModel

- (void)setEntity:(FDFeedEntity *)entity {

if (!entity) return ;

_entity = entity;

CGFloat maxLayout = ([UIScreen mainScreen].bounds.size.width - 20.f);

CGFloat space = 10.f;

CGFloat bottom = 4.f;

//title

NSMutableAttributedString *title = [[NSMutableAttributedString alloc] initWithString:entity.title];

title.yy_font = Font(16.f);

title.yy_color = [UIColor blackColor];

YYTextContainer *titleContainer = [YYTextContainer containerWithSize:CGSizeMake(maxLayout, CGFLOAT_MAX)];

_titleLayout = [YYTextLayout layoutWithContainer:titleContainer text:title];

CGFloat titleX = 10.f;

CGFloat titleY = 10.f;

CGSize titleSize = _titleLayout.textBoundingSize;

_titleFrame = (CGRect){titleX,titleY,CGSizeMake(titleSize.width, titleSize.height)};

//cell Height

_cellHeight = (CGRectGetMaxY(_titleFrame) + bottom);

}

@end

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

UITableViewCell 處理 :

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {

self = [ super initWithStyle:style reuseIdentifier:reuseIdentifier];

if (!self) return nil;

YYLabel *title = [YYLabel new ];

title.displaysAsynchronously = YES; //開啟異步渲染

title.ignoreCommonProperties = YES; //忽略屬性

title.layer.borderColor = [UIColor brownColor].CGColor;

title.layer.cornerRadius = 1.f;

title.layer.borderWidth = 1.f;

[self.contentView addSubview:_titleLabel = title];

return self;

}

賦值:

- (void)setModel:(FrameYYModel *)model {

if (!model) return ;

_model = model;

self.titleLabel.frame = model.titleFrame;

self.titleLabel.textLayout = model.titleLayout; //直接取 YYTextLayout

}

Auto Layout 搭配異步渲染

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

CGFloat maxLayout = [UIScreen mainScreen].bounds.size.width - 20.f;

self.titleLabel.preferredMaxLayoutWidth = maxLayout;

self.subTitleLabel.preferredMaxLayoutWidth = maxLayout;

self.contentLabel.preferredMaxLayoutWidth = maxLayout;

優缺點

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

其它

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

label.layer.cornerRadius = 5.f;

label.clipsToBounds = YES;

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

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

總結

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

最后附上 Demo

非常好我支持^.^

(0) 0%

不好我反對

(0) 0%

      發表評論

      用戶評論
      評價:好評中評差評

      發表評論,獲取積分! 請遵守相關規定!

      ?
      主站蜘蛛池模板: xxxx性xx另类 | 亚洲男人天堂2021 | 4438x全国最大色 | 天天摸天天碰成人免费视频 | 欧美三级网站 | 人人公开免费超级碰碰碰视频 | 日本又粗又长一进一出抽搐 | 国产精品理论片在线观看 | 国产色婷婷 | 欧美性f | 色女仆影院 | 奇米狠狠操 | 国产精品久久久久影视不卡 | 欧美大胆一级视频 | 91青草视频 | 依依成人精品无v国产 | 国产成年网站v片在线观看 国产成人91青青草原精品 | eee在线播放成人免费 | 午夜影院免费观看 | 久久91精品牛牛 | 中国xxxxx高清免费看视频 | 激情婷婷| 亚洲欧美卡通 动漫 丝袜 | 中文字幕一精品亚洲无线一区 | 天天综合色天天综合网 | 男女交性视频播放视频视频 | 日本色免费 | 免费看美女午夜大片 | 欧美三级成人 | 国产免费高清在线精品一区 | 国产精品久久久亚洲 | sese国产| 欧美 亚洲 国产 丝袜 在线 | 欧美jizzhd精品欧美4k | 伊人伊成久久人综合网777 | 天天干天天爱天天射 | 中文字幕一二三区乱码老 | 色你懂的 | 日本三级理论 | 2021国产精品成人免费视频 | 日本免费在线一区 |