Auto Layout ,是苹果公司提供的一个基于约束布局,动态计算视图大小和位置的库,苹果公司早在 iOS 6 系统时就引入了 Auto Layout,并且已经集成到了 Xcode 开发环境里。
那么,Auto Layout 到底是如何实现自动布局的,这种布局算法会影响性能吗?
Cassowary 算法
Cassowary 能够有效解析线性等式系统和线性不等式系统,用来表示用户界面中那些相等关系和不等关系
。基于此,Cassowary 开发了一种规则系统,通过约束来描述视图间的关系。约束就是规则,这个规则能够表示出一个视图相对于另一个视图的位置。
由于 Cassowary 算法让视图位置可以按照一种简单的布局思路来写,这些简单的相对位置描述可以在运行时动态地计算出视图具体的位置。视图位置的写法简化了,界面相关代码也就更易于维护。苹果公司也是看重了这一点,将其引入到了自己的系统中。
Cassowary 算法由 Alan Borning、Kim Marriott、Peter Stuckey 等人在“Solving Linear Arithmetic Constraints for User Interface Applications”论文中提出的,为了能方便开发者更好地理解 这个算法,并将其运用到更多的开发语言中,作者还将代码发布到了他们搭建的 Cassowary 网站上。
由于 Cassowary 算法本身的先进性,更多的开发者将 Cassowary 运用到了各个开发语言中,比如 JavaScript、.NET、Java、Smalltalk、C++ 都有对应的库。
Auto Layout 的生命周期
Auto Layout 不只有布局算法 Cassowary,还包含了布局在运行时的生命周期等一整套布局引擎系统,用来统一管理布局的创建、更新和销毁,是 Auto Layout 的核心
,主导着整个界面布局。
每个视图在得到自己的布局之前,Layout Engine 会将视图、约束、优先级、固定大小通过计算转换成最终的大小和位置。
Constraints Change
表示的就是约束变化,添加、删除视图时会触发约束变化。Activating 或 Deactivating,设置 Constant 或 Priority 时也会触发约束变化。Layout Engine 在碰到约束变化后会重新计算布局,获取到布局后调用 superview.setNeedLayout(),然后进入 Deferred Layout Pass。
Deferred Layout Pass
主要作用是做容错处理
。如果有些视图在更新约束时没有确定或缺失布局声明的话,会先在这里做容错处理。接下来,Layout Engine 会从上到下调用 layoutSubviews(),通过 Cassowary 算法计算各个子视图的位置,算出来后将子视图的 frame 从 Layout Engine 里拷贝出来。在这之后的处理,就和手写布局的绘制、渲染过程一样了。
使用 Auto Layout 和手写布局的区别,就是多了布局上的这个计算过程
触发约束变化 —> Layout Engine就需要重新计算布局,会先获取到当前的布局,调用SuperView.SetNeedLayout() —> Deffered Layout Pass进行监听 —> Layout Engine 从上到下调用LayoutSubViews(),通过Cassowary算法计算各个子视图的位置,算出来后将子视图的Frame从Layout Engine里拷贝出来 —> 和手写布局的绘制、渲染一样。
Auto Layout 性能问题
上图是 WWDC 2018 中 202 Session 里讲到的 Auto Layout 在 iOS 12 中优化后的表现。可以看到,优化后的性能,已经基本和手写布局一样可以达到性能随着视图嵌套的数量呈线性增长了。而在此之前的 Auto Layout,视图嵌套的数量对性能的影响是呈指数级增长的。
iOS 12 之前,很多约束变化时都会重新创建一个计算引擎 NSISEnginer 将约束关系重新加进来,然后重新计算。结果就是,涉及到的约束关系变多时,新的计算引擎需要重新计算,最终导致计算量呈指数级增加。
iOS12 的 Auto Layout 更多地利用了 Cassowary 算法的界面更新策略,使其真正完成了高效的界面线性策略计算。
03 | Auto Layout 是怎么进行自动布局的,性能如何?
参考链接:https://github.com/ming1016/study/wiki/深入剖析Auto-Layout,分析iOS各版本新增特性
网友评论