0%

Autolayout指南·调试 AutoLayout·无法满足的布局

008-Autolayout指南·调试 AutoLayout

无法满足的布局

当系统无法为当前的约束集合找到可行解时就会出现无法满足的布局。两个或更多所需的约束会因为它们不能同时为真而冲突。

辨别无法满足的布局

一般来说 IB 就可以在设计时期检测出冲突,在这种情况下 IB 会有多种方法来展示这个错误。

  • 冲突的约束会在画布上标红
  • Xcode 会在 issue navigator 中将冲突约束作为警告罗列出来
  • IB 会在文档大纲的右上角展示一个红色箭头

点击箭头会罗列出所有当前布局里的 Autolayout 问题。

IB 经常能够为这些问题提供建议的修复方案,当然也可以在 AutoLayout 的帮助信息里查看更多解决 ViewController、Window、Root View 的冲突问题的方法。

注意

尽管 IB 提供的即时反馈能方便地创建出可行的布局,但并不能找到所有可能的布局错误。

例如,IB 只能检测出画布当前尺寸下的冲突,然而一些冲突只会在根视图伸展或压缩超过某个点才会出现(或者当内容伸展或压缩超出某个点时)。IB 无法检测出这样的错误。

所以即使你修复了所有 IB 显式提示的问题和错误也是不够的,你仍然需要在运行时里测试各种屏幕尺寸、方向、动态字体大小、你希望支持的语言下你的布局的显式情况。

当系统在运行时检测到一个无法满足的布局时,它会执行下列步骤

  • AutoLayout 识别出冲突约束的集合
  • 打破冲突约束集合中的某一个约束后检查布局,直到找到一个可行解
  • AutoLayout 将冲突和被打破的约束的信息打印到控制台

这套反馈系统能使应用继续运行,同时仍能尝试向用户展示一些有意义的信息。然而打破约束造成的影响可能因布局不同而变化很大,甚至不同的构建之间也会有很大变化。

在许多情况下,缺失的约束可能没有任何明显的效果,视图层级可能仍然像你期待的那样展示。但也有一些情况下,缺失的约束将导致视图层级整个部分错位、缩放或者消失不显示。

当这些错误没有明显影响时可能会容易被忽视,毕竟它们并不会改变应用的表现效果。但是任何对视图层级或 SDK 的改变都可能会改变被打破的约束集合,从而造成一个明显破损的布局。

所以应当在检测出无法满足的布局时始终坚持修复它们,为 UIViewAlertForUnsatisfiableConstraints 打符号断点可以帮助你确认你在测试时捕捉到了不明显的错误。

预防无法满足的布局

无法满足的约束相对容易修复,系统会在无法满足的约束出现时告诉你并提供给你一系列冲突的约束。

一旦你知道了这些错误,解决方法一般就很直接了。要么移除其中一个约束,要么将其改成可选的约束。

然而也有一些常见的错误需要你进行更细致的检查:

  • 当你用编程的方式向视图层级中添加 view 时经常会出现无法满足的布局。新的 view 的 translatesAutoresizingMaskIntoConstraints 属性默认为 YES(译者注:Masonry 会在 make、update、remake 的时候设置其为 NO)。当你尝试向画布中的 view 添加约束时,IB 会自动设置该属性为 NO。但是如果你使用编程方式创建和放置你的 view,你就需要在添加约束前手动设置其为 NO。
  • 当一个视图层级被显示在一个远小于它尺寸的空间时会出现无法满足的约束。

你通常可以预测到你的 view 所需要的最小尺寸的空间并正确设计你的布局。但是国际化和动态字体都会造成 view 的内容远大于你期望的大小。伴随着排列方式的可能性逐渐增加,确保布局能够在所有状况下正常工作将会显著地困难起来。

Instead, you may want to build in failure points, so that your layout fails in a predictable, controlled manner.(不知道怎么翻译了、、)

可以考虑将一些必须的约束转换为高优先的可选约束,这可以帮助你在发生冲突时控制布局的哪些地方需要被打破。

例如,将你的容错点的优先级设置为 999,在大多无情况下这样的高优先级和必需优先级并没有什么区别。然而一旦冲突出现,高优先级约束就会被打破,从而保护剩余的布局。

类似的,避免给一个有 intrinsic content size 的 view 设置必需的 content-hugging 或 compression-resistance 优先级。一般而言,控制器的尺寸就是一个理想的容错点,控制器可以变得稍微大一些或者小一些,同时对布局不会造成过于显著的影响。

的确,有些控制器只能按照其 intrinsic content size 大小来展示,然而即使是这样的情况,使控制器有几 pt 的错误也比使布局按照无法预测的方式破损的效果要好很多。