iOS 8 的自动布局问题,代码在 iOS 7 上运行良好

Posted

技术标签:

【中文标题】iOS 8 的自动布局问题,代码在 iOS 7 上运行良好【英文标题】:Autolayout problems with iOS8 with code that works fine on iOS7 【发布时间】:2014-09-23 05:03:02 【问题描述】:

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

上周,当 Apple 宣布 iOS8 已准备好迎接黄金时段时,我将我的一部 iPhone 和一部 iPad 都升级到了 iOS8。我还将我的 XCODE 升级到了第 6 版。我有第二部 iPhone,我留在 iOS7 时。

我使用 Xcode 6 生成了新的可执行文件,当我在运行 iOS8 的设备上执行它们的屏幕布局时,我很苦恼,但在 iOS7 上仍然可以。在我的物理设备和 Xcode 的模拟器上都是如此。

花了很多时间挖掘,但我现在很清楚发生了什么,虽然我不知道为什么。

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

一些涉及我放置在其大小等于屏幕大小的底层视图上的按钮的示例:

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

(2) 如果我要求自动布局使按钮的宽度等于底层视图宽度的 50%,它根本没有宽度。

我能够通过以下方式解决这些问题:

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

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

我正在慢慢摸索自己的方式,使用这些变通方法,回到适用于 iOS7 和 iOS8 的自动布局代码。但我真的很想知道这里发生了什么。

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

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

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

有人对这里可能出现的问题有任何建议或想法吗?

【问题讨论】:

我在同一条船上。无论如何,看起来你的底层视图的宽度是 0 开始宽度,因此当你告诉你的按钮的中心 X 是底层视图的中心 X 时,按钮出现在左边缘。 是的,就我目前所见,一旦我开始在视图上放置控件,我就可以使用这些控件之间自动布局关系的所有不同变体。即,一个按钮的水平中心可以毫无问题地与另一个按钮对齐。 我还应该提到我没有使用 IB。我所有的自动布局代码都是通过直接构造 NSLayoutConstraint/s 来完成的。一直都是这样做的,并且在 iOS7 中完美运行。 作为更新,我仍在努力解决这个问题,试图深入了解它。 见***.com/questions/25954831/… 【参考方案1】:

@robmayoff 对此有一个很好的答案:https://***.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 中,您需要在 containerView 上请求布局:

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

【讨论】:

BFar,这是个好消息,而且很有道理。我迫不及待想尝试一下,看看我能否解决这个问题。 @BFar 能否请您整理一个简单的示例项目来演示此问题(例如适用于 7 SDK,但不适用于 8 SDK),然后提交雷达并共享雷达#? BFar,我尝试了 robmayoff 的想法,但它们似乎与我的问题无关。我现在有一个合法的解决方法,所以我正在努力。谢谢!【参考方案2】:

您可能会发现此问题的答案很有帮助:UICollectionView cell subviews do not resize

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

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

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

self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;

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

绝对讨厌我们花了这么多时间处理这些烦人的问题。

【讨论】:

普拉内思,谢谢。我已经尝试过了,但它不会影响我遇到的问题。 嗯,很遗憾听到这没有帮助。就我而言,我混合了 IB 约束,然后在运行时对代码进行了调整,这解决了我的问题。祝你好运。【参考方案3】:

就我而言,问题与标记为UIView-Encapsulated-Layout-WidthUIView-Encapsulated-Layout-Height 的约束有关。当我删除它们时,一切都表现得好像我的视图大小为零,一切都集中在屏幕的左上角。当我把它们留在里面时,新的约束按预期工作。我还保留了标记为_UILayoutSupportConstraint 的约束。

【讨论】:

以上是关于iOS 8 的自动布局问题,代码在 iOS 7 上运行良好的主要内容,如果未能解决你的问题,请参考以下文章

iOS 7 和 8 中 UITableViewCells 的自动布局指标不同

iOS:在 iOS 7 和 iOS 8 上将约束应用于子视图的自动布局差异

iOS 自动布局 ios 7 与 ios 8

iOS 7 自动布局与 iOS 8 自适应布局,有区别吗?

iOS 7 与 iOS 8 自动布局问题

高度的自动布局在 iOS 8 中工作但在 iOS 7 中不工作