使用 NSLayoutAnchor 不好吗?

Posted

技术标签:

【中文标题】使用 NSLayoutAnchor 不好吗?【英文标题】:Is using NSLayoutAnchor bad? 【发布时间】:2018-09-11 02:54:11 【问题描述】:

我通常使用 NSLayoutAnchor,但很多时候我被建议不要使用它。除了更复杂/更长的代码之外,它是否有任何问题,例如性能下降?

有人告诉我要使用:

let myView = UIView(frame: CGRect(x: 0, y: 20, width: view.frame.bounds.width, height: 100))

代替:

let myView = UIView()
myView.translatesAutoresizingMaskIntoConstraints = false
myView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
myView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
myView.topAnchor.constraint(equalTo: view.topAnchor, constant: 20).isActive = true
myView.heightAnchor.constraint(equalToConstant: 100).isActive = true

【问题讨论】:

仅供参考 - 您创建带有框架的视图的行非常好,如果您添加该行,它将与约束完全相同:myView.autoresizingMask = [ .flexibleWidth, .flexibleBottomMargin ] 【参考方案1】:

首先,我想确认使用框架比自动布局快得多(据我所知大约是 10 倍)。这就是为什么另一个告诉你使用框架而不是自动布局的原因。虽然@RakeshaShastri 有一个很好的答案来解释为什么我们应该使用自动布局,但我的答案将讨论什么时候应该使用框架而不是自动布局。


在视图控制器上显示UIViewUIButtonUILabel...等普通视图时,可以使用自动布局。使用框架和自动布局之间的区别是微不足道的。 对于UICollectionViewCellUITableViewCell,您应该使用框架。在这种情况下,框架布局和自动布局之间的性能存在很大差异。

让我们看看下面的基准来比较它们。

图片来自LayoutFrameworkBenchmark。它在布局 100 个 UICollectionView 单元格时显示性能

如您所见,自动布局比手动布局和非自动布局花费更多的时间(约 15 倍)。这种差异会影响您的集合视图在滚动时的流畅程度。

特别是当您的单元格具有繁重的视图层次结构时,自动布局将花费大量时间来基于具有多余计算的约束来计算单元格子视图的位置。它可以使集合视图或表格视图在滚动时滞后。在这里使用框架可以尽可能地减少多余的计算,并帮助我们节省其他任务的时间。


结论:

UICollectionViewCellUITableViewCell 上使用自动布局时要小心。如果您的集合视图或表格视图在滚动时不流畅,自动布局可能是一个重要原因。

仅当您遇到自动布局问题时才使用框架。在正常情况下使用框架获得的性能是微不足道的。

【讨论】:

图表似乎有点偏差。为什么有比手动布局更快的方法? @Cristik 有趣的问题。我检查了手动布局基准的源代码。每次调用layoutSubviews 时,它都会更改子视图的框架。这也许就是原因。使用更快的方法,frame 只有在新帧与当前帧不同时才应更改。将当前帧分配给view.frame 会触发多余的动作,从而降低性能。 这听起来是一个合理的理由,但想知道真正的用例 - layoutSubviews 会发生多少次被调用并且不需要更改帧? 除了第一次调用layoutSubviews,其他时候不需要改变帧。正如我在运行 LayoutFrameworkBenchmark 后检查的那样,layoutSubviews 在每个单元格上被调用 0 到 10 次,无需更改。 layoutSubviews 通常由于帧更改或由于调用 setNeedsLayout/updateLayoutIfNeeded 而被调用,基准测试是否以某种方式强制了比需要更多的布局?【参考方案2】:

使用框架缺点是,一旦你将它们布置好,你需要在需要时手动更改它们以相对于某些东西进行更改。例如:方向改变、动画等。但是如果你使用 autolayout,你将定义视图的相对位置,这意味着,即使在方向改变或动画的情况下,你的视图也会自行调整大小根据你设置的约束。

关于性能下降,自动布局需要更多时间(不是那么多)来计算视图的框架,但这可以忽略不计,并且方便的方式掩盖了性能影响。

最后,考虑到大多数视图都需要基于屏幕尺寸、方向变化等的某种动态定位,框架的用例将非常非常小。混合框架和自动布局从来都不是好主意。


Tl;dr - 自动布局 > 帧。

【讨论】:

【参考方案3】:

如果您担心复杂/冗长的代码,请尝试使用 SnapKit。它让你爱上自动布局https://github.com/SnapKit/SnapKit

话虽如此,很多人倾向于认为 AutoLayout VS Frame。但实际上你应该同时使用两者。如果您的视图不会改变并且需要快速交互,请使用 Frame。如果您希望视图可扩展并处理横向/纵向,请使用 AutoLayout。

【讨论】:

以上是关于使用 NSLayoutAnchor 不好吗?的主要内容,如果未能解决你的问题,请参考以下文章

使用 NSLayoutAnchor.constraintEqualToSystemSpacingAfter 时的控制台警告

使用 NSLayoutAnchor 时清除约束

NSLayoutAnchor 的类型

扩展 NSLayoutAnchor 中的编译错误

Nil 与预期的参数类型 'NSLayoutAnchor<NSLayoutDimension>' Swift 3 不兼容

将可视格式的约束转换为 NSLayoutAnchor API