一般优化的思路:

  1. 提前计算并缓存好高度(布局),因为heightForRowAtIndexPath:是调用最频繁的方法。

  2. 复杂界面可采用异步绘制。

  3. 在大量图片展示时,可以滑动时按需加载。

  4. 尽量少用或不用透明图层,多个透明元素重叠显示可采用合并成一张图片显示。

  5. 减少subviews的数量,如果是不需要交互可以使用CALayer 替换掉 UIView。

  6. heightForRowAtIndexPath:中尽量不使用cellForRowAtIndexPath:

  7. 根据场景合理使用imageWithContentsOfFile和imageNamed。

  8. 页面元素多的时候,减少autolayout布局,采用frame。

  9. 缓存NSDateFormatter结果,不多次创建,及时释放。

  10. 图片解码时,CALayer 被提交到 GPU 前,CGImage 中的数据才会得到解码,GPU执行,卡主线程。常见的做法是在后台线程先把图片绘制到 CGBitmapContext 中,然后从 Bitmap 直接创建图片。

  11. CALayer 的 border、圆角、阴影、遮罩(mask)触发的离屏渲染,可开启CALayer.shouldRasterize ,转嫁到CPU上或是截图或者采用图片实现。

  12. 使用RunLoop和多线程在闲时处理一些繁重的计算工作。

缓存高度

提前计算好 cell 的高度和布局

// 关于UITableView有两个重要的方法
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;

iOS8后,会边滑动边调用heightForRowAtIndexPath:这个方法; 想想一下, 如果把计算cell高度的方法写在这儿, 不仅每次都会调用计算方法, 而且重复滑动的话, 还会再次计算; 所以我们一般在网络请求结束后,更新界面之前就把每个 cell 的高度算好,缓存到相对应的 model 中。

异步绘制

在Cell上添加系统控件的时候,实质上系统都需要调用底层的接口进行绘制,当我们大量添加控件时,对资源的开销也会很大,所以我们可以索性直接绘制,提高效率。

//异步绘制
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, ), ^{
CGRect rect = CGRectMake(, , , );
UIGraphicsBeginImageContextWithOptions(rect.size, YES, );
CGContextRef context = UIGraphicsGetCurrentContext();
[[UIColor lightGrayColor] set];
CGContextFillRect(context, rect); //将绘制的内容以图片的形式返回,并调主线程显示
UIImage *temp = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext(); // 回到主线程
dispatch_async(dispatch_get_main_queue(), ^{
//code
});
});

减少层级

减少SubViews的数量, 在滑动的列表上,多层次的view会导致帧数的下降。
例如: 绘制 cell 不建议使用 UIView,建议使用 CALayer。
从形式来说:UIView 的绘制是建立在 CoreGraphic 上的,使用的是 CPU。CALayer 使用的是 Core Animation,CPU,GPU 通吃,由系统决定使用哪个。View的绘制使用的是自下向上的一层一层的绘制,然后渲染。Layer处理的是 Texure,利用 GPU 的 Texture Cache 和独立的浮点数计算单元加速 纹理 的处理。

从事件的响应来说:UIView是 CALayer 的代理,layer本身并不能响应事件,因为layer是直接继承自NSObject,不具备处理事件的能力。而 UIView 是继承了UIResponder 的,这也是事件转发的角度上说明,view要比单纯的layer复杂的多。多层次的view再加上各种手势的处理势必导致帧数的下降。

hide

尽量少用addView给Cell动态添加View,可以初始化时就添加,然后通过hide来控制是否显示

避免离屏渲染

为了保证TableView的流畅,当快速滑动的时候,cell必须被快速的渲染出来。所以cell渲染的速度必须快。如何提高cell的渲染速度呢?

  • 当有图像时,预渲染图像,在bitmap context先将其画一遍,导出成UIImage对象,然后再绘制到屏幕,这会大大提高渲染速度。具体内容可以自行查找“利用预渲染加速显示iOS图像”相关资料。
  • 渲染最好时的操作之一就是混合(blending)了,所以我们不要使用透明背景,将cell的opaque值设为Yes,背景色不要使用clearColor,尽量不要使用阴影渐变等
  • 由于混合操作是使用GPU来执行,我们可以用CPU来渲染,这样混合操作就不再执行。可以在UIView的drawRect方法中自定义绘制。

当然除了这些, 还有其他的优化方法:

  • 正确地使用UITableViewCell的重用机制
  • 避免阻塞主线程
  • 按需加载
  • 尽可能重用开销比较大的对象
  • 尽量减少计算的复杂度

tableView优化思路的更多相关文章

  1. mysql优化思路

    /* mysql优化思路     1.数据库设计     2.sql语句优化     3.数据库参数设置     4.恰当的硬件资源和操作系统        数据库设计         数据的3NF( ...

  2. 补充:tableView优化总结

    tableView优化方式总结 (说明:一下只是我自己的小总结,会有不足,望大神指正,多谢大家了) 1 缓存 cell 的行高.目的方便第二遍访问 cell. 2 减少图片的blend 操作.包括:设 ...

  3. redis在实践中的一些常见问题以及优化思路

    1.fork耗时导致高并发请求延时 RDB和AOF的时候,其实会有生成RDB快照,AOF rewrite,耗费磁盘IO的过程,主进程fork子进程 fork的时候,子进程是需要拷贝父进程的空间内存页表 ...

  4. 谈一款MOBA类游戏《码神联盟》的服务端架构设计与实现(更新优化思路)

    注:本文仅用于在博客园学习分享,还在随着项目不断更新和完善中,多有不足,暂谢绝各平台或个人的转载和推广,感谢支持. 一.前言 <码神联盟>是一款为技术人做的开源情怀游戏,每一种编程语言都是 ...

  5. Spring配置表友好性优化思路

    Spring配置表需要尽量保证对程序员的友好性,一下提供一种优化思路. 中途未保存,心态炸了,只贴图了,fuuuuuuuuuuuuuck 第一种(最烂,最不友好):以Json的格式保存在配置表中,程序 ...

  6. PHP优化思路

    想起来记录一下自己对PHP的优化思路 针对Nginx和 PHP-FPM进行优化 首先应该分为代码层面.配置层面.架构层面 代码层面 参见了https://segmentfault.com/a/1190 ...

  7. 转:使用RNN解决NLP中序列标注问题的通用优化思路

    http://blog.csdn.net/malefactor/article/details/50725480 /* 版权声明:可以任意转载,转载时请标明文章原始出处和作者信息 .*/ author ...

  8. 【58沈剑架构系列】mysql并行复制优化思路

    一.缘起 mysql主从复制,读写分离是互联网用的非常多的mysql架构,主从复制最令人诟病的地方就是,在数据量较大并发量较大的场景下,主从延时会比较严重. 为什么mysql主从延时这么大? 回答:从 ...

  9. MySQL order by的一个优化思路

    最近遇到一条SQL线上执行超过5s,这显然无法忍受了,必须要优化了. 首先看眼库表结构和SQL语句. CREATE TABLE `xxxxx` ( `id` ) NOT NULL AUTO_INCRE ...

随机推荐

  1. Linux RCU 机制详解

    1.简介: RCU(Read-Copy Update)是数据同步的一种方式,在当前的Linux内核中发挥着重要的作用. RCU主要针对的数据对象是链表,目的是提高遍历读取数据的效率,为了达到目的使用R ...

  2. 探索哪个进程使磁盘I/O升高

    如果生产环境中磁盘使用率突然升高,却不知道因为哪个应用程序导致的,这个时候我们可以使用pidstat命令来查看,比如 Linux .el7.x86_64 (ip.ec2.internal) _x86_ ...

  3. 【日常开发】使用多种工具实现 sql查询没有结果的name

    本文地址 分享提纲: 1. 事情的背景 2. 解决办法 3. 总结 1. 事情的背景 现在需要将2000条数据的name,从user表中查询出来结果,sql 这样写 SELECT * FROM use ...

  4. 用navicat手动删除了数据表的记录,再次写入的时候,怎么让id重新从1开始?

    问:用navicat手动删除了mariadb数据表的记录,再次写入的时候,自增id会继续,不会从1开始. 比如,原来有10条记录,全部清空,再次写入数据,id会从11开始,怎么让他重新从1开始呢? 重 ...

  5. [国家集训队]JZPFAR

    嘟嘟嘟 k-d tree模板之二:查询第k大距离.(所以是怎么上黑的) 因为k-d tree的查询就是暴力嘛,所以我就想到了一个很暴力的做法:每一次查询用一个长度为k的优先队列维护.按距离递增,编号递 ...

  6. springboot 传值到页面

    每天学习一点点 编程PDF电子书.视频教程免费下载:http://www.shitanlife.com/code   <!DOCTYPE html> 2 <html> 3 &l ...

  7. 水题,P1789 【Mc生存】插火把 (暴力即可)

    #include<cstdio> #define maxn int(1e4) bool dp[maxn][maxn]; int n; void f1(int x, int y) { dp[ ...

  8. 对Promise的理解?

    ES6原生提供了promise对象 所谓Promise,就是一个对象,用来传递异步操作的消息.它代表了某个未来才会知道结果的事件(通过是一个异步操作),并且这个事件提供统一的API,可供进一步处理 P ...

  9. 利用原生JS实现网页1920banner图滚动效果

    内容描述:随着PC设备硬件性能的进步和分辨率的不断提高,现在主流网站逐渐开始采用1920banner图,为适应这一趋势,博主设计了1920banner图的滚动效果,代码利用了原生JS实现了1920ba ...

  10. docker官方文档学习-1-Docker for mac安装配置

    https://docs.docker.com/docker-for-mac/ Get started with Docker for Mac 首先像在本博客docker-1-环境安装及例子实践处将环 ...