iOS性能优化-预排版
参考地址:https://blog.ibireme.com/2015/11/12/smooth_user_interfaces_for_ios/
前面一篇说了异步绘制文字,异步渲染图片,这篇主要是预排版,经过这三种处理之后,基本上已经非常流畅了.
下面的demo就使用了这三种处理来做优化.
我使用的demo是我之前做的一个列表:https://www.cnblogs.com/alan12138/p/9619336.html
下面是优化前的demo地址和效果:
github:https://github.com/alan12138/InfoFlow

可以看到滑动很快的时候到最后已经达到33FPS的程度了,当然如果正常浏览不那么快的时候还是没有很大差别的.
下面是优化后的demo地址和效果:
github:https://github.com/alan12138/Interview-question/tree/master/3/InfoFlow

可以看到无论如何滑动,基本稳定在60FPS.
因为图片异步渲染和异步绘制文字我上一篇博文已经写过了所以这篇主要写一下预排版.
预排版主要做的就是这件事:
dispatch_async(dispatch_get_global_queue(, ), ^{
//造一些数据
self.feeds = [NSMutableArray array];
for (int i = ; i < ; i++) {
APMyFeed *myFeed = [[APMyFeed alloc] init];
myFeed.headIcon = @"https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=2118739199,3378602431&fm=26&gp=0.jpg";
myFeed.name = @"王者小能手";
myFeed.sex = @"性别女";
...
}
myFeed.time = @"5分钟前";
myFeed.location = @"南京·麒麟国际企业研发园";
myFeed.comment = @"";
myFeed.zan = @"";
myFeed.expand = NO;
[self.feeds addObject:myFeed];
}
self.layouts = [NSMutableArray array];
for (APMyFeed *feed in self.feeds) {
APMyFeedLayout *layout = [[APMyFeedLayout alloc] init];
layout.feed = feed;
[self.layouts addObject:layout];
}
dispatch_async(dispatch_get_main_queue(), ^{
[self.mainTableView reloadData];
});
});
获取数据之后,异步将所有控件排版通过已获取的数据提前计算出来,并保存在一个数组中,处理完之后再返回主线程刷新列表加载数据.
数组中的每个元素都是APMyFeedLayout类型,其中保存了每一条的数据和通过数据计算出来的排版数据.如此所有控件的排版和行高计算都已经在列表加载之前完成了,避免了滑动过程中的大部分计算,所以在滑动过程中只剩下了一件事,就是把计算好的数据赋值而已.
#pragma mark - UITableView
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.layouts.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
APMyFeedTableViewCell *cell = [APMyFeedTableViewCell cellWithTableView:tableView]; APMyFeedLayout *layout = self.layouts[indexPath.row];
cell.layout = layout;
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
APMyFeedLayout *layout = self.layouts[indexPath.row];
return layout.height;
}
排版的计算在APMyFeedLayout中进行,主要就是在setFeed的时候通过feed数据计算出每个控件的frame,并保存在每个APMyFeedLayout对象中,用于后面使用.
@implementation APMyFeedLayout
- (void)setFeed:(APMyFeed *)feed {
_feed = feed;
CGFloat screenW = [UIScreen mainScreen].bounds.size.width;
self.iconRect = CGRectMake(, , , );
CGFloat nameW = [CommonUtils calcWidthWithTitle:feed.name font:nameFont];
CGFloat nameH = [CommonUtils calcLabelHeight:feed.name fontSize:nameFont width:nameW];
self.nameRect = CGRectMake(CGRectGetMaxX(self.iconRect) + , , nameW, nameH);
self.sexRect = CGRectMake(CGRectGetMaxX(self.iconRect) + , CGRectGetMaxY(self.nameRect) + , , );
...
self.seperatorViewRect = CGRectMake(, CGRectGetMaxY(self.delRect) + , screenW, );
self.height = CGRectGetMaxY(self.seperatorViewRect);
}
@end
最后就是在cell中赋值了:
- (void)setLayout:(APMyFeedLayout *)layout {
_layout = layout;
[self.headIconBtn sd_setImageWithURL:[NSURL URLWithString:layout.feed.headIcon] forState:UIControlStateNormal];
self.headIconBtn.frame = layout.iconRect;
[self.headIconBtn addRadius:self.headIconBtn.bounds.size.width / corners:UIRectCornerAllCorners bgColor:[UIColor whiteColor]];
self.nameLabel.text = layout.feed.name;
self.nameLabel.frame = layout.nameRect;
[self.sexIconView setImage:[UIImage imageNamed:layout.feed.sex]];
self.sexIconView.frame = layout.sexRect;
self.contentLabel.text = layout.feed.content;
self.contentLabel.frame = layout.contentRect;
self.timeLabel.text = layout.feed.time;
self.timeLabel.frame = layout.timeRect;
self.locationLabel.text = layout.feed.location;
self.locationLabel.frame = layout.locationRect;
self.delBtn.frame = layout.delRect;
self.zanLabel.text = layout.feed.zan;
self.zanLabel.frame = layout.zanLabelRect;
self.commentLabel.text = layout.feed.comment;
self.commentLabel.frame = layout.commentLabelRect;
...
}
iOS性能优化-预排版的更多相关文章
- 【腾讯Bugly干货分享】微信读书iOS性能优化
本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/578c93ca9644bd524bfcabe8 “8小时内拼工作,8小时外拼成长 ...
- IOS 性能优化的建议和技巧
IOS 性能优化的建议和技巧 本文来自iOS Tutorial Team 的 Marcelo Fabri,他是Movile的一名 iOS 程序员.这是他的个人网站:http://www.marcelo ...
- iOS性能优化:Instruments使用实战
iOS性能优化:Instruments使用实战 最近采用Instruments 来分析整个应用程序的性能.发现很多有意思的点,以及性能优化和一些分析性能消耗的技巧,小结如下. Instrument ...
- iOS性能优化总结
iOS性能优化总结.关于 iOS 性能优化梳理: 基本工具.业务优化.内存优化.卡顿优化.布局优化.电量优化. 安装包瘦身.启动优化.网络优化等. 关于iOS 性能优化梳理: 基本工具.业务优化.内存 ...
- iOS 性能优化收集
iOS 性能调试 instrument Instrument Instrument之Core Animation工具 避免图层混合 ①.确保控件的opaque属性设置为true,确保backgroun ...
- 微信读书 iOS 性能优化总结
微信读书作为一款阅读类的新产品,目前还处于快速迭代,不断尝试的过程中,性能问题也在业务的不断累积中逐渐体现出来.最近的 1.3.0 版本发布后,关于性能问题的用户反馈逐渐增多,为此,团队开始做一些针对 ...
- iOS 性能优化总结
卡顿产生的原因 在 VSync信号到来后,系统图形服务会通过 CADisplayLink等机制通知 App,App主线程开始在 CPU中计算显示内容,比如视图的创建.布局计算.图片解码.文本绘制等.随 ...
- iOS性能优化-数组、字典便利时间复杂
上图是几种时间复杂度的关系,性能优化一定程度上是为了降低程序执行效率减低时间复杂度. 如下是几种时间复杂度的实例: O(1) return array[index] == value; 复制代码 O( ...
- <转>iOS性能优化:Instruments使用实战
最近采用Instruments 来分析整个应用程序的性能.发现很多有意思的点,以及性能优化和一些分析性能消耗的技巧,小结如下. Instruments使用技巧 关于Instruments官方有一个很有 ...
随机推荐
- 《Fluent Python》---一个关于memoryview例子的理解过程
近日,在阅读<Fluent Python>的第2.9.2节时,有一个关于内存视图的例子,当时看的一知半解,后来查了一些资料,现在总结一下,以备后续查询: 示例复述 添加了一些额外的代码,便 ...
- Java日志框架总结
1. 前言 从写代码开始,就陆陆续续接触到了许多日志框架,较常用的属于LOG4J,LogBack等.每次自己写项目时,就copy前人的代码或网上的demo.配置log4j.properties或者lo ...
- 【Spring】 AOP Base
1. AOP概述 2. AOP的术语: 3. AOP底层原理 4. Spring 中的AOP 4.1 概述 4.2 分类 4.3 Spring的传统AOP 针对所有方法的增强:(不带有切点的切面) 带 ...
- virtualbox下最小化安装centos7后上网设置
在虚拟机中以最小化方式安装centos7,后无法上网,因为centos7默认网卡未激活. 可以设置 文件 /etc/sysconfig/network-scripts/ifcfg-enp0s3 将 O ...
- MultipartFile 获取上传TXT文件字数
@ResponseBody @RequestMapping(value = "/addImgForDynamic")//(发布动态) public Map addImgForDyn ...
- innobackupex备份参数slave-info、safe-slave-backup
mysql物理备份用的比较多的是innobackupex命令,备份常用,但对于里面的两个参数slave-info.safe-slave-backup一直搞的不太明白,今儿亲测了一下. 先解释一下参数意 ...
- 【深入浅出-JVM】(77):SPI
概念 Service Provider Interface 规则 在resource/META-INF/services 创建一个以接口全限定名为命名的文件,内容写上实现类的全限定名 接口实现类在cl ...
- git之rebase、merge和cherry pick的区别(面试常问)
git flow图例镇楼 merge 这个简单,初学者常用.比如主分支是Dev,最新版本是01.然后小明基于此,搞了个feature 分支A,业务:打酱油.然后在上面多次提交,完成功能迭代开发,如A1 ...
- apache ignite系列(六): 服务网格
简介 服务网格本质上还是远程方法调用(RPC),而在ignite中注册的服务本质体现还是以cache的形式存在,集群中的节点可以相互调用部署在其它节点上的服务,而且ignite集群会负责部署服务的 ...
- opencv中IplImage* src = cvLoadImage,错误
在调试这段代码时 IplImage* src = cvLoadImage("D:\\图像\\已处理 - 11.26\\1.jpg", 1); 提示一下错误 引发了异常: 读取访问权 ...