AutoLayout

Sunday, March 15, 2020

AutoLayout

AutoLayout 的常用用法这里就不详细说明了,网络资料很多,一般而言,因为他复杂的写法,会用一些第三方库的语法糖来写,比如 Masonary, SnapKit等,另外注意一些特别的场景的使用就好,比如在scrollView里使用。

很多人一直不大愿意去使用这个,一方面也是习惯使然(习惯 frame 的方式了),另一方面也是担心 AutoLayout 的性能,不过在 iOS12之后,这个性能问题得以大幅度改善了

AutoLayout 性能问题

  • AutoLayout 的前身,也就是它的布局算法,其实是借鉴于Cassowary(1997年)的布局算法的。

AutoLayout 的生命周期

  • AutoLayout 不只有布局算法(Cassowary),还包含了一套布局在运行时的生命周期等一整套布局引擎,用来管理布局的创建,更新,销毁,这个引擎叫做 Layout Engine

  • Layout Engine 会将视图,约束,优先级,固定大小这些设置的参数计算转换成最终的大小和位置,每当约束变化,就会触发 Deffered Layout Pass,重新计算,结束后就会进入监听约束变化的状态。一直循环

AutoLayout生命周期

性能问题

  • 在 iOS12以前,Autolayout 的性能,随着页面的复杂度(视图嵌套越来越复杂)增加,对性能的影响是呈指数级的

Cassowary 他解决的是界面的线性规划问题,而解法用的是 Simplex 算法,simplex 算法多数情况是不会有指数级的时间复杂度的,而 Cassowary 更是优化了 simplex,所以更加不会出现这个问题。

问题出在哪

在 iOS12之前,每次约束变化,会重新创建一个计算引擎NSISEnginer 将约束关心重新加进来,然后重新计算。每次都重新计算,导致计算量指数级增加。

iOS12的解决

iOS12的 AutoLayout 更多地利用了 Cassowary 的更新界面的策略,使其达到了高效的界面线性策略计算。

AuotLayout 的几个更新方法

  • setNeedsLayout: 告知页面要更新,但不会立刻开始,执行后会调用 layoutSubViews
  • layoutIfNeed: 告知页面立刻更新,一般配合 setNeedsLayout 使用,如果需要立刻生成新的 frame 就用这个,一般用这个来配合动画代码
  • layoutSubViews: 系统重写布局

AutoLayout 计算 UITableView 的 Cell 的高度

主要是 UILabel 的问题,这里需要注意几个设置,一个是要设置preferredMaxLayoutWidth, 还有ContentHuggingPriority要设置为UILayoutPriorityRequried

  • iOS8以上,Cell 的高度的 dataSource return 为 UITableViewAutomaticDimension
  • iOS8以前,那就是老路子了,手动计算 cell 的高度,然后缓存到 model 的一个属性中,这里就不具体细说了。
iOS

链表习题

RunLoop 介绍