iOS8的自动布局问题,代码在iOS7上运行良好



我正在为iPhone和iPad开发应用程序。它支持iOS6和iOS7,并且只使用自动布局。

上周,当苹果宣布iOS8已进入黄金时段时,我将一部iPhone和一部iPad都升级为iOS8。我还将XCODE升级到了版本6。我有第二部iPhone,我把它留在iOS7。

我用Xcode 6生成了新的可执行文件,当我在运行iOS8但在iOS7上运行时,看到它们的屏幕布局被打乱,我很难过。在我的物理设备和Xcode的模拟器上都是如此。

这花了很多时间,但我现在很清楚发生了什么,尽管我不知道为什么。

具体来说,某些自动布局操作在iOS8上对我来说是失败的,但在iOS7上它们很好。

一些例子涉及一个按钮,我把它放在一个大小等于屏幕大小的底层视图上:

(1) 如果我要求自动布局将按钮的水平中心(CX)定位为与基础视图的水平中心相等,结果是按钮的水平中央位于基础视图的左边缘。

(2) 如果我要求auto layout使按钮的宽度等于基础视图宽度的50%,那么它根本没有宽度。

我能够解决以下问题:

(1) 我要求自动布局将按钮的中心位置设置为等于基础视图的左边缘加上屏幕宽度的50%。

(2) 我要求自动布局使按钮的宽度等于屏幕宽度的50%。

通过这样的解决方案,我慢慢地找到了在iOS7和iOS8上都适用的自动布局代码。但我真的很想知道这里发生了什么。

看起来自动布局无法确定基础视图的大小,因此需要该信息的自动布局计算失败。但它确实知道视图的上边缘和左边缘在哪里,因此基于这些数据的计算是成功的。

这是一个大型应用程序,我已经为iOS6和iOS7编写了数百行自动布局代码,非常适合我

我已经用iOS8调整和尝试了三天,我并不比刚开始的时候更聪明。

有人对这里的问题有什么建议或想法吗?

@robmayoff对此有一个很好的答案:https://stackoverflow.com/a/26066992/1424669

本质上,在iOS8中,您不能再对视图调用setNeedsUpdateConstraintssetNeedsLayout,也不能期望更新子视图的约束。

必须对约束正在更改的视图调用这些方法。这与iOS7向后兼容。

示例:

假设您有一个具有根视图self.view的ViewController和一个名为containerView的子视图。containerView附加了一个NSLayoutConstraint,您想更改它(在本例中为顶部空间)。

在iOS7中,您可以通过请求根视图的新布局来更新VC中的所有约束:

self.containerView_TopSpace.constant = 0;
[self.view setNeedsUpdateConstraints];
[self.view setNeedsLayout];

在iOS8中,您需要请求容器上的布局View:

self.containerView_TopSpace.constant = 0;
[self.containerView setNeedsUpdateConstraints];
[self.containerView setNeedsLayout];

您可能会发现这个问题的答案很有用:UICollectionView单元格子视图不会调整的大小

在大多数情况下,iOS7中的工作(而不是iOS 8上的工作)自动布局问题似乎源于iOS 8中根视图的大小不正确,特别是当我们将translatesAutoresizingMaskIntoConstraints设置为NO时。对于我的视图,我能够在layoutSubviews(或任何具有正确边界的适当初始值设定项)中设置根视图的框架,这解决了问题。

self.contentView.frame = CGRectInset(self.bounds, 0, 0);

如上面的答案所示,你也可以做

self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;

然后在开始在代码中设置自己的约束之前,将translatesAutoresizingMaskIntoConstraints转回NO。

真讨厌我们花那么多时间在这些烦人的杂烩上。

在我的案例中,问题与标记为UIView-Encapsulated-Layout-WidthUIView-Encapsulated-Layout-Height的约束有关。当我移除它们时,所有的东西都表现得好像我的视图是零大小的,所有的都集中在屏幕的左上角。当我把它们放在里面时,新的约束正如预期的那样起作用。我还保留了标记为_UILayoutSupportConstraint的约束。

最新更新