首页 技术 正文
技术 2022年11月13日
0 收藏 343 点赞 3,990 浏览 2568 个字

参考地址:https://blog.ibireme.com/2015/11/12/smooth_user_interfaces_for_ios/

很久以前就看过这篇文章,但是也只是看过就过了,没有去整理思路,最近有时间把一些点整理一下.

通读下来可以总结一下对性能优化,在这里也就是提高界面流畅度的宗旨只有一句话唯而已:把能异步执行的都尽量异步执行.

在我这篇里主要记录一下文本的异步绘制,先上两个视频,异步处理前后的差异,我直接把YYFPSLabel拿过来用了,检测FPS的变化情况:

iOS性能优化-异步绘制

可以看到,在滑动很快的时候,FPS最低已经达到了20几.

iOS性能优化-异步绘制

经过异步绘制处理之后,可以看到无论如何滑动,FPS一直保持在60.

这是我写的一个小demo:https://github.com/alan12138/Interview-question/tree/master/3/AsyncLabel,也就是上面运行案例的代码.

前后对比的效果就是将cell中的label使用UILabel和使用自定义label之后的效果.

首先,其实这种优化是对流畅度非常敏感的界面来说的,一般场景很少需要做这样的优化,并且,只有在文字非常多且复杂,滑动非常快的时候才能明显的感觉到差别.

如果项目中某个地方需要优化,而你也想尝试一下使用YYAsyncLayer,并且对文字的处理比较简单,可以将demo中的ATLabel拿来参考,当然直接使用YYLabel是最好的选择,ATLabel只是用来演示YYAsyncLayer的使用,并且非常简陋.

不谈YYLabel内部各种复杂的处理,他是直接继承自UIView,自己造了个Label控件出来,但是从异步绘制的角度来说,其原理就是,将本来UILabel所做的绘制文字的工作拿过来自己做,并放在子线程异步执行.

下面简单分析一下YYAsyncLayer的内部原理:

其中涉及到了四个类:

<!–
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #a31515; background-color: #efffec}
–>

YYAsyncLayer

<!–
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #000000; background-color: #efffec}
–>

YYTransaction

<!–
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #000000; background-color: #efffec}
–>

YYSentinel

<!–
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #000000; background-color: #efffec}
–>

YYDispatchQueuePool

先从YYTransaction开始说起,每一个YYTransaction对象相当于一个异步绘制任务.

ATLabel中在以下需要调用重绘的方法中都提交了contentsNeedUpdated任务,

iOS性能优化-异步绘制

查看commit方法可以看到,他使用了一个Set来存储这些任务.并且在其中调用了一个方法:YYTransactionSetup

iOS性能优化-异步绘制

看一下YYTransactionSetup方法:

iOS性能优化-异步绘制

可以看到这个方法中的代码只会执行一次,也就是在第一次commit 的时候执行一次,只会便不会再执行了.方法内部初始化了一个Set对象,用来收集绘制任务,并做了runloop监听,在runloop等待和退出之前,也就是空闲的时候,调用回调方法.

iOS性能优化-异步绘制

而在这个回调方法中,便是执行所有收集到的绘制任务.

综上所述,在label需要重绘的时候,作者将绘制任务收集起来,并在runloop空闲的时候一起执行.

接下来看一下作者是如何执行这些任务的:

可以看到每个绘制任务都是调用display方法,而display中执行的_displayAsync方法便是对异步绘制的处理,也就是说每个绘制任务最终都会调用到这个方法.

iOS性能优化-异步绘制

_displayAsync方法:

iOS性能优化-异步绘制

在ATLabel中可以看到

iOS性能优化-异步绘制

作者重写了layerClass方法,并返回了YYAsyncLayer.class,也就是将当前label的layer替换为了YYAsyncLayer.然后便可以通过实现YYAsyncLayer的代理方法newAsyncDisplayTask.将ATLabel我们自己对文字绘制的实现异步执行,可以看到是在异步代码块中.

上面圈出来的便是对代理中task.display代码实现的调用.

回到YYAsyncLayer的 _displayAsync方法,可以看到最后回到主线程将绘制内容赋值,便完成了整个流程.

iOS性能优化-异步绘制

最后,还有作者一些细节性的处理我没有写下来,有兴趣可以自己研究一下,比如计数器的使用,hash的处理,队列数量的控制,作者短短的几百行代码凝聚了很多智慧.

<!–
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #000000; background-color: #efffec}
–>
<!–
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #000000; background-color: #efffec}
–>
<!–
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #000000; background-color: #efffec}
–>
<!–
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #000000; background-color: #efffec}
–>
<!–
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #2b839f; background-color: #efffec}
span.s1 {color: #000000}
–>

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,023
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,513
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,361
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,143
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,774
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,853