AutoLayoutShorthand 1.0

AutoLayoutShorthand 1.0

测试已测试
语言语言 Obj-CObjective C
许可证 MIT
发布最新版本2014年12月

未认领维护。



  • 作者:
  • Jonathan 'Wolf' Rentzsch

Auto Layout Shorthand

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 参考

Auto Layout Shorthand 是一个穷人版的 DSL,嵌入到正常的 Objective-C 字典字面量中。

每个键值对都包含创建一个 NSLayoutConstraint 所需的信息。这与 VFL 形成对比,其中一条字符串可以生成多个约束。

字典键编码了两个信息:NSLayoutConstraint 的 firstAttributerelation。以下是一些示例

  • @"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_bottomals_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,但在我看来,概念上的清晰度值得更复杂的实现。

版本历史

v1.0: 2014 年 4 月 6 日

v0.4:Jun 24, 2013

  • [新增] 改进了处理约束组(常见情况)的方式。

    • 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部分中提到的方法来添加/获取约束的方式。还有覆盖之前设置的约束的想法。

v0.3:Jun 18, 2013

  • [开发] 再次统一UIView和NSView实现。

v0.2:May 22, 2013

v0.1.1:Apr 24, 2013

  • [修复] 让Closest-Common-Superview更宽容。

v0.1:Apr 22, 2013

  • 初始版本。

    正如其语义化版本所暗示的,其界面可能会以破坏客户端的方式更改。


  1. 实际上+[NSLayoutConstraint constraintsWithVisualFormat:…]将创建一个具有NSLayoutAttributeLeading属性的约束,而上面的示例使用的是NSLayoutAttributeLeft。ALS除了支持@"leading =="之外,我还想要让示例对于尚未了解Auto Layout的右对齐文本系统支持的读者来说很简单。

  2. 与上述1相同。