iOS layout

330 阅读2分钟

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进行资源处理,所以纹理尽量不要超过这个尺寸