layout
1.setNeedsLayout:就算没有任何UI上的改动,也会在下一个更新周期中layoutsubviews。
2.layoutIfNeeded:在调用前没有UI上的改动,是不会在当前更新周期中layoutsubviews的。
3.layoutSubviews:1和2都是通过调用它来实现布局的,但请别直接调用它,在代码中我们很难在恰当的时机调用它,可能会造成某些性能上的浪费。
contraint
1.setNeedsUpdateConstraints:调用 setNeedsUpdateConstraints()会保证在下一次更新周期中更新约束,这个方法和 setNeedsDisplay() 以及 setNeedsLayout() 方法的工作机制类似。
2.updateConstraintsIfNeeded:它会检查 “update constraints”标记(可以被 setNeedsUpdateConstraints 或者 invalidateInstrinsicContentSize方法自动设置),如果它认为这些约束需要被更新,它会立即触发 updateConstraints()。
3.updateConstraints:1和2都是通过调用它来实现自动布局的,但请别直接调用它,在代码中我们很难在恰当的时机调用它,可能会造成某些性能上的浪费。
iOS的 mainRunloop是一个60fps(120fps的在2021年出来了)的回调,也就是说每16.7ms(VSync信号时间)会绘制一次屏幕,这个时间段内要完成view的缓冲区创建,view内容的绘制(如果重写了drawRect),这些CPU的工作。然后将这个缓冲区交给GPU渲染,这个过程又包括多个view的拼接(compositing),纹理的渲染(Texture)等,最终显示在屏幕上。整个过程就是我们上面画的流程图。 因此,如果在16.7ms内完不成这些操作,比如,CPU做了太多的工作,或者view层次过于多,图片过于大,导致GPU压力太大,就会导致“卡”的现象,也就是丢帧.
滑动优化方案思路:
-
CPU:
- 对象的创建、调整、销毁可以放在子线程中去做ASDK;
- 预排班。布局计算、文本计算等事先放到子线程中去做;
- 使用轻量级对象,比如CALayer代替UIView
- 预渲染。文本等异步绘制,图片编解码等。
- 控制并发线程数量
- 减少重复计算布局,减少修改frame等
- autolayout比frame更消耗资源
- 可以让图片的size跟frame一致
-
GPU:
- 纹理渲染。避免离屏渲染
- 视图混合。减少视图层级的复杂性,减少透明视图;不透明的opaque设置为YES
- GPU能处理的最大纹理是4096 * 4096,一旦超过这个尺寸就会调用CPU进行资源处理,所以纹理尽量不要超过这个尺寸