Auto Layout Shorthand (ALS) 是创建和添加 Auto Layout 约束的替代系统。
感觉有点像 CSS,但更强大,没有 HTML 那令人沮丧的默认布局模型。
以下是一个示例来介绍 ALS
[iconView als_addConstraints:@{
@"left ==": als_superview,
@"width ==": @(kIconWidth),
@"top ==": als_superview,
@"height ==": @(kIconHeight),
}];
以下是大部分相同示例,使用视觉格式语言 (VFL)
[iconView addConstraints:@[
[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[iconView(kIconWidth)]"
options:0
metrics:NSDictionaryOfVariableBindings(kIconWidth)
views:NSDictionaryOfVariableBindings(iconView)],
[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[iconView(kIconHeight)]"
options:0
metrics:NSDictionaryOfVariableBindings(kIconHeight)
views:NSDictionaryOfVariableBindings(iconView)],
]];
并大多数与此相同的示例,使用 +[NSLayoutConstraint constraintWithItem:…]
[iconView addConstraints:@[
[NSLayoutConstraint constraintWithItem:iconView
attribute:NSLayoutAttributeLeft
relatedBy:NSLayoutRelationEqual
toItem:iconView.superview
attribute:NSLayoutAttributeLeft
multiplier:1.0
constant:0.0],
[NSLayoutConstraint constraintWithItem:iconView
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1.0
constant:kIconWidth],
[NSLayoutConstraint constraintWithItem:iconView
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:iconView.superview
attribute:NSLayoutAttributeTop
multiplier:1.0
constant:0.0],
[NSLayoutConstraint constraintWithItem:iconView
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1.0
constant:kIconHeight],
]];
Auto Layout Shorthand 是一个穷人版的 DSL,嵌入到正常的 Objective-C 字典字面量中。
每个键值对都包含创建一个 NSLayoutConstraint 所需的信息。这与 VFL 形成对比,其中一条字符串可以生成多个约束。
字典键编码了两个信息:NSLayoutConstraint 的 firstAttribute
和 relation
。以下是一些示例
@"width >-Agent"
@"height <-Agent"
@"centerX ==-Agent"
对于键的第一个部分,属性,除 NSLayoutAttributeNotAnAttribute
之外的所有 NSLayoutAttribute
都受支持。请参阅以下 ALS 字典键名 列表(我们将在一会儿讨论 ALS 字典值名)
NSLayoutAttribute 常量 | ALS 字典键名 | ALS 字典值名 |
---|---|---|
NSLayoutAttributeLeft | left | als_left |
NSLayoutAttributeRight | right | als_right |
NSLayoutAttributeTop | top | als_top |
NSLayoutAttributeBottom | bottom | als_bottom |
NSLayoutAttributeLeading | leading | als_leading |
NSLayoutAttributeTrailing | trailing | als_trailing |
NSLayoutAttributeWidth | width | als_width |
NSLayoutAttributeHeight | height | als_height |
NSLayoutAttributeCenterX | centerX | als_centerX |
NSLayoutAttributeCenterY | centerY | als_centerY |
NSLayoutAttributeBaseline | baseline | als_baseline |
字典键的第二个部分以明显的方式编码 NSLayoutRelation
NSLayoutRelation 常量 | Auto Layout Shorthand 等价于 |
---|---|
NSLayoutRelationLessThanOrEqual | <= |
NSLayoutRelationEqual | == |
NSLayoutRelationGreaterThanOrEqual | >= |
字典值编码一个关系或常量。简单的 关系和 常数可以直接赋值
@"top ==": headerView.als_bottom
@"width ==": @(42)
让我们再深入讨论一下 headerView.als_bottom
。 als_bottom
是作为一个类别添加到 UIView
中的方法。自动布局简写添加了一组方法,一个对应每个 NSLayoutAttribute
。那上方就是:ALS 字典值名称 列。
这些类别可以让您在一个表达式中引用视图和属性。结果是,一个简单的类,仅将两者包装成一个对象,稍后由 -[UIView(AutoLayoutShorthand) als_addConstraints:]
消耗。
您可以使用字典来指定更复杂的约束
@"top ==": @{als_view:headerView.al_bottom, als_constant:@(10)},
@"width ==": @{als_constant:@(42), als_priority:@(UILayoutPriorityDefaultHigh)]
支持以下关键字
自动布局简写关键字 | 对应的 NSLayoutConstraint 属性 |
---|---|
als_view | secondItem |
als_multiplier | multiplier |
als_constant | constant |
als_priority | priority |
最后,VFL 有 @"|"
,代表父视图。als_superview
是 ALS 的同一种形式的实现。
比 +[NSLayoutConstraint constraintWithItem:…]
更简洁,但功能一样强大。实际上,更强大一些,因为您可以在创建时指定约束的优先级。
比 +[NSLayoutConstraint constraintWithItem:…]
更容易阅读和理解。
通常比视觉格式语言(Visual Format Language)更简洁,但功能更强大(自动布局简写可以指定 centerX 和 centerY)。
易于重构。视觉格式语言字符串对 Xcode 的重构支持是透明的。这会导致如果使用重构重命名变量或属性而忘记更新任何相应的 VFL 字符串时,出现的运行时异常。
视图属性友好。这段代码看起来不工作
[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[self.iconView(32)]"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(self.iconView)];
可能是因为 self.
。一种解决办法是直接访问 ivar
[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_iconView(32)]"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(_iconView)];
但我不是很高兴这样做,因为它绕过了访问器。我建议自己创建字典
[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[iconView(32)]"
options:0
metrics:nil
views:@{@"iconView": self.iconView}];
或使用 ALS。
内置最近的共同父视图发现。当关联视图之间的属性时,自动布局简写会自动计算视图最近的共同父视图,并在其中添加生成的约束。这是 Apple 推荐放置约束的地方。
另一种依赖。不过也请不要担心,它是一个自包含的 .h/.m 对。
又一件要学习的事情。你可能无论如何都要学习 VFL 才能理解 Auto Layout 的调试日志。
鼓励您考虑将约束应用到目标视图本身,而不是它们实际添加到的父视图。我认为移除这种间接性是值得的。
就像只有上帝可以创造一棵树,只有 VFL 可以创建 NSSpacers。幸运的是,ALS 与 VFL 很好地协同工作,所以如果你想利用间距,就要使用 VFL。
编写一个示例应用程序来展示常见场景。
将 als_superview
升级到 UIView 或完全删除它。可能前者更合适——它并不是绝对必需的(你始终可以使用 myview.superview
,但在我看来,概念上的清晰度值得更复杂的实现。
[更改] 允许任一视图为最低共同祖先。 (Andrew Hershberger)
[修复] 隐式转换警告。 (Andrew Hershberger)
[修复] 优先级不起作用。 (Joe Szymanski)
[新增] 改进了处理约束组(常见情况)的方式。
als_addConstraints:现在返回其创建的约束数组。
als_activateConstraints和als_deactivateConstraints的NSArray类别方法允许启用和禁用NSLayoutConstraint组。
结合上述als_addConstraints:,这允许您创建约束组,根据用户交互和应用状态轻松切换其开或关。
als_hostView和als_setHostView:的NSLayoutConstraint类别方法处理视图与约束的一对一关系((UI|NS)View <->> NSLayoutConstraint
),并追踪约束分配到的宿主视图,以便可以在运行时轻松地激活(添加)和禁用(移除)。
als_isActive和als_setActive:的NSLayoutConstraint类别方法提供单个约束激活控制。由als_activateConstraints & als_deactivateConstraints使用。
这取代了我之前在TODO部分中提到的方法来添加/获取约束的方式。还有覆盖之前设置的约束的想法。
初始版本。
正如其语义化版本所暗示的,其界面可能会以破坏客户端的方式更改。
实际上+[NSLayoutConstraint constraintsWithVisualFormat:…]
将创建一个具有NSLayoutAttributeLeading
属性的约束,而上面的示例使用的是NSLayoutAttributeLeft
。ALS除了支持@"leading =="
之外,我还想要让示例对于尚未了解Auto Layout的右对齐文本系统支持的读者来说很简单。
与上述1相同。