Hi,SwiftGG 翻译组启用了新的域名:swiftgg.team今后翻译组的各项活动将会在新域名下开展,不要错过哦!

作者:Dominik Hauser,原文链接,原文日期:2015-08-12
译者:SergioChan;校对:shanks;定稿:小锅

Auto Layout是一件很神奇的事情。像一个巫师一样告诉元素应该去什么位置并且让他们守规矩。你并不需要亲自将元素放到那些位置去。感觉像是天地因为你的咒语而将他们移动了。

但是你应该在什么时候念“咒语”呢?换句话说,当你没有使用界面生成器(Interface Builder)的时候,你应当把Auto Layout的代码放在哪呢?

UIView 的方法 updateConstraints 的文档我们可以看到:

设置自定义视图约束需要通过重载这个方法来完成。

因为有这句话,我总是认为苹果是在要求我把布局的代码放到这个方法里。那么问题就来了:这个方法会被 UIKit 调用至少两次,重复添加相同的约束就会导致错误。我在网上找到的最佳途径是在视图类中添加一个布尔值的属性,并且在 updateConstraints() 去赋值,这样就可以保证你只运行了一次布局的代码。

文档里还写到:

当你的自定义视图发现有一个属于它的约束忽然失效了,它会马上移除这个约束,然后调用 setNeedsUpdateConstraints 来告知视图它的约束需要被更新。

这就意味着 updateConstraints() 应该在视图中的约束因为某些事件而改变的情况下使用。而且这个方法的名字在这个场景下也更加的有意义。

在我的几乎所有的布局中约束都是固定的。当然,有些事情我也需要改变一个约束中的常量。我可以无需移除并重新添加这个约束。(NSLayoutConstraint 中的常量是它在被创建之后唯一能被修改的东西了。)

正因为此,我开始将布局代码都放到 init(frame:) 里去。但是有了上面文档提到的那些内容。我还是觉得不太适应。

后来在今年的 WWDC 上,有一个苹果的工程师就是建议这么做的。而且就在昨天,我收到了一个关于 updateConstraints() 没有被调用的问题的回复 —— 至少我称之为 bug。结果我发现它并不是一个bug。

苹果工程师这么写道:

总的来说,如果约束只会被创建一次,它就应该被放在初始化方法中完成,例如 -init 或者 -viewDidLoad 等等。留着 updateConstraints 给那些在程序运行时可能改变的布局。

不错。当我对于代码的感觉被苹果推荐的时候,我挺享受的。

这里有一个示例,里面你能看到我把布局代码放在哪里了。

写布局的同志们加油吧!

对了,如果你喜欢这篇文章,请关注我的 feed

更新:Ole Begemann 在他的博客中写了一篇 When should you implement updateConstraints

本文由 SwiftGG 翻译组翻译,已经获得作者翻译授权,最新文章请访问 http://swift.gg

文章目录