2015 Session 219 Mysteries of Auto Layout, Part 2

地址 Mysteries of Auto Layout, Part 2 (opens new window) 参考示例地址 QingSession (opens new window)

每一次的 session 笔记都不算是分享,一种简单的记录复习 & 感悟咯,强烈建议自己看一遍

# 涉及 Tip

  • translatesAutoresizingMaskIntoConstraints 设置成 false 就好啦
  • Layout Constraint Creation 新的 Constraint API
  • Constraint identifier
  • Debug

# Layout Constraint Creation

参考示例 [2015-session-219] -> [2015-session-219]

这个一定是我们期待很久的东西了。

NSLayoutConstraint(item:b, attribute:.Top, relatedBy:.Equal, toItem:view,
    attribute:.Top, multiplier:1, constant:10)
NSLayoutConstraint(item:b, attribute:.Leading, relatedBy:.Equal,
    toItem:view, attribute:.Leading, multiplier:1, constant:10)

这是以往的布局 API ,怪不得大家都会去用 Masonry 或者 SnapKit 。

不管 Apple 怎么去改布局的 API ,仍然是反人类,但是这次的可以让我们有所期待了~

b.topAnchor.constraintEqualToAnchor(view.topAnchor, constant:10)
b.leadingAnchor.constraintEqualToAnchor(view.leadingAnchor, constant:10)

好啦,如果你直接贴这样的代码基本会呵呵的。

切记设置 translatesAutoresizingMaskIntoConstraints = false ,忘了就会很惨很惨。

然后记得 active 你添加的约束,像这样:

imageView.centerXAnchor.constraintEqualToAnchor(margins.centerXAnchor).active = true
imageView.centerYAnchor.constraintEqualToAnchor(margins.centerYAnchor).active = true

还有一点要注意的是添加约束前先将 View 添加上去~,比如 view.addSubview(imageView)

我建议的书写顺序是:

  1. 创建一个 View
  2. 设置 View 的各种内容,比如 label 就是 text
  3. 设置 translatesAutoresizingMaskIntoConstraints
  4. addSubView
  5. 添加 constraint

具体可以看 Demo 。

# 错误用法

Jesse 给出了一些错误的用法,这些用法我们完全可以从逻辑上判断出问题。

label.leadingAnchor.constraintEqualToConstant(100)

编译不过去的~ 这里缺少指明 label 的 leading 和谁有 100 的 point 。

label.leadingAnchor.constraintEqualToAnchor(view.widthAnchor)

leading 怎么和 width 扯上关系 ==

# Constraint identifier

听说你要 debug ,那怎么能不设置 identifier

没设置的:

"<_UILayoutSupportConstraint:0x14630d40 V:[_UILayoutGuide:0x14538610(0)]>",
"<_UILayoutSupportConstraint:0x14627b90 V:|-(0)-[_UILayoutGuide:0x14538610]
(Names: '|':UIView:0x14538470 )>",
"<NSLayoutConstraint:0x146778d0 UIImageView:0x146707c0.height ==
0.6*UIView:0x145831a0.height>",
"<NSLayoutConstraint:0x14677930 UILabel:0x14670f70’Photo caption'.centerY
<= UIView:0x145831a0.centerY>",
"<NSLayoutConstraint:0x146774e0 V:[_UILayoutGuide:0x14580ff0]-(NSSpace(8))-
[UIImageView:0x146707c0]>",
"<NSLayoutConstraint:0x14677550 V:[UIImageView:0x146707c0]-(NSSpace(8))-
[UILabel:0x14670f70’Photo caption']>"

设置的:

"<_UILayoutSupportConstraint:0x14630d40 V:[_UILayoutGuide:0x14538610(0)]>",
"<_UILayoutSupportConstraint:0x14627b90 V:|-(0)-[_UILayoutGuide:0x14538610] (Names: '|':UIView:0x14538470 )>",
"<NSLayoutConstraint:0x1464b4d0 'photoHeight' UIImageView:0x14644300.height == 0.6*UIView:0x14538470.height>",
"<NSLayoutConstraint:0x1464b530 'captionToCenterY' Caption for photo.centerY <= UIView:0x14538470.centerY (Names: Caption for photo:0x14644ab0 )>",
"<NSLayoutConstraint:0x1464b0e0 'topVerticalArray' V:[_UILayoutGuide:0x14538610]-(NSSpace(8))-[UIImageView:0x14644300]>",
"<NSLayoutConstraint:0x1464b0e0 'topVerticalArray' V:[UIImageView:0x14644300]-(NSSpace(8))-[Caption for photo] (Names: Caption for photo:0x14644ab0 )>"

好吧,然而这并没有什么卵用。当然不是!除了在这里方便查找,我们用 identifier 记录每条约束都是做什么,以后修改也会方便很多的~

extension NSLayoutConstraint {
    /* For ease in debugging, name a constraint by setting its identifier, which will be printed in the constraint's description.
     Identifiers starting with UI and NS are reserved by the system.
     */
    @available(iOS 7.0, *)
    public var identifier: String?
}

# Debug

具体的 Debug 我觉得还是看 session 和 Guide 比较好。

  • 调用 constraintsAffectingLayoutForAxis: 查看相关的约束
  • 调用 _autolayoutTrace 查看布局层级
  • Xcode 中有一个 Debug -> View Debugging 可以玩玩看
  • 调用 hasAmbiguousLayout 查看是否有懵逼的布局
  • 调用 exerciseAmbiguityInLayout 执行一种系统尝试解决的布局方案

# 参考阅读

AutoLayout 有一本书写的不错,直达链接 iOS Auto Layout开发秘籍(第2版) [iOS Auto Layout Demystified Second Edition] (opens new window)

官方的指导还是要看的: Auto Layout Guide (opens new window)