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

时间:2021-03-15 23:01:01

I'm in the midst of developing an app for the iPhone and iPad. It supports iOS6 and iOS7 and it uses auto layout exclusively.

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

This past week, when Apple announced that iOS8 was ready for prime-time, I upgraded one of my iPhones and an iPad both to iOS8. I also bumped my XCODE up to version 6. I have 2nd iPhone which I left at iOS7.

上周,当苹果(Apple)宣布iOS8已经为黄金时段做好准备时,我将我的一款iphone和一款iPad都升级为iOS8。我还将我的XCODE升级到版本6。我在iOS7有第二部iPhone。

I generated new executables with Xcode 6 and I was distressed to see that their screen layouts were messed up when executed on my devices running iOS8 but still fine on iOS7. This is true on both my physical devices and on Xcode's emulators.

我用Xcode 6生成了新的可执行文件,当在运行iOS8的设备上执行时,他们的屏幕布局出现了混乱,但在iOS7上仍然没问题,这让我很难过。在我的物理设备和Xcode的模拟器上都是如此。

It took a lot of digging but I'm pretty clear now on what's happening though I don't know why.

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

Specifically, certain auto layout operations are failing for me on iOS8 but they are fine on iOS7.

具体来说,某些自动布局操作在iOS8上失败了,但在iOS7上没有问题。

Some examples involving a button which I am placing on an underlying view whose size is equal to the size of the screen:

下面是一些例子,我把一个按钮放在一个基础视图上,这个视图的大小等于屏幕的大小:

(1) If I ask auto layout to position the button's horizontal center (CX) equal to the underlying view's horizontal center, the result is that the button's horizontal center is placed on the underlying view's left edge.

(1)如果我要求auto layout将按钮的水平中心(CX)定位为底层视图的水平中心,那么结果就是按钮的水平中心位于底层视图的左边缘。

(2) If I ask auto layout to to make the width of the button equal to 50% of the width of the underlying view, it gives it no width at all.

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

I am able to work around these issues as follows:

我能够解决以下问题:

(1) I ask auto layout to position the button's center equal to the underlying view's left edge plus 50% of the screen's width.

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

(2) I ask auto layout to make the button's width equal to 50% of the screen's width.

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

I am slowly clawing my way, with workarounds like these, back to auto layout code that works for me on both iOS7 and iOS8. But I am really wondering what's going on here.

我正在慢慢地摸索着自己的方法,使用这些变通方法,回到iOS7和iOS8上都适用的自动布局代码。但我真的想知道这是怎么回事。

It looks like auto layout cannot determine the size of the underlying view and so auto layout calculations that require that information fail. But it does know where the top and left edges of the view are so calculations based on those data succeed.

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

This is a large app and I've written many hundreds of lines of auto layout code for iOS6 and iOS7 that work perfectly for me.

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

I've been tweaking and trying things now with iOS8 for three days and I'm no wiser than I was when I began.

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

Anyone have any suggestions or thoughts as to what might be the issue here?

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

3 个解决方案

#1


11  

@robmayoff has a great answer for this: https://*.com/a/26066992/1424669

@robmayoff有一个很好的答案:https://*.com/a/26066992/1424669。

Essentially, in iOS8 you can no longer call setNeedsUpdateConstraints and setNeedsLayout on a view and expect the constraints of subviews to update.

本质上,在iOS8中,您不能再对视图调用setneedsupdateconstr和setNeedsLayout,并期望子视图的约束进行更新。

You must call these methods on the view whose constraint is changing. This is backwards compatible to iOS7.

您必须在约束发生变化的视图上调用这些方法。这是向后兼容iOS7的。

EXAMPLE:

例子:

Suppose you have a ViewController with root view self.view and a subview called containerView. containerView has a NSLayoutConstraint attached to it that you want to change (in this case, top space).

假设你有一个具有根视图self的视图控制器。视图和名为containerView的子视图。containerView有一个要更改的NSLayoutConstraint(在本例中为顶部空间)。

In iOS7 you could update all constraints in a VC by requesting a new layout for the root view:

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

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

In iOS8 you need to request layouts on the containerView:

在iOS8中,您需要在containerView中请求布局:

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

#2


3  

You might find the answers to this question helpful: UICollectionView cell subviews do not resize

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

In most cases the works in iOS7 but not on iOS 8 auto layout problems seem to stem from the root view not being sized correctly in iOS 8, particularly when we set translatesAutoresizingMaskIntoConstraints to NO. For my views I was able to set the root view's frame in layoutSubviews (or whichever appropriate initializer that does have the correct bounds) and this resolved the issue.

在大多数情况下,iOS7中的工作,而不是iOS 8的自动布局问题,似乎源于iOS 8中的根视图没有被正确地调整大小,尤其是当我们将translatesautoresizingmaskintoconstraint设置为NO时。对于我的视图,我能够在layoutSubviews中设置根视图的框架(或者任何具有正确边界的合适的初始化器),这就解决了问题。

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

As shown in the answer above, you could also do

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

self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;

and then turn translatesAutoresizingMaskIntoConstraints back to NO before you start setting your own constraints in code.

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

Definitely hate that so much of our time is taken with these annoying gotchas.

绝对讨厌我们的时间被这些烦人的陷阱占用。

#3


0  

In my case, the problem related to constraints labeled UIView-Encapsulated-Layout-Width and UIView-Encapsulated-Layout-Height. When I removed them, everything behaved as though my view was of zero size, with everything centered on the upper left corner of the screen. When I left them in, new constraints worked as expected. I also retained the constraints labeled _UILayoutSupportConstraint.

在我的例子中,这个问题与被标记为uiview -封装- layout - width和uiview -封装- layout - height的约束有关。当我移除它们时,所有的东西都表现得好像我的视图是零大小的,所有的东西都集中在屏幕的左上角。当我把它们放进去时,新的约束就会像预期的那样工作。我还保留了名为_UILayoutSupportConstraint的约束。

#1


11  

@robmayoff has a great answer for this: https://*.com/a/26066992/1424669

@robmayoff有一个很好的答案:https://*.com/a/26066992/1424669。

Essentially, in iOS8 you can no longer call setNeedsUpdateConstraints and setNeedsLayout on a view and expect the constraints of subviews to update.

本质上,在iOS8中,您不能再对视图调用setneedsupdateconstr和setNeedsLayout,并期望子视图的约束进行更新。

You must call these methods on the view whose constraint is changing. This is backwards compatible to iOS7.

您必须在约束发生变化的视图上调用这些方法。这是向后兼容iOS7的。

EXAMPLE:

例子:

Suppose you have a ViewController with root view self.view and a subview called containerView. containerView has a NSLayoutConstraint attached to it that you want to change (in this case, top space).

假设你有一个具有根视图self的视图控制器。视图和名为containerView的子视图。containerView有一个要更改的NSLayoutConstraint(在本例中为顶部空间)。

In iOS7 you could update all constraints in a VC by requesting a new layout for the root view:

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

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

In iOS8 you need to request layouts on the containerView:

在iOS8中,您需要在containerView中请求布局:

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

#2


3  

You might find the answers to this question helpful: UICollectionView cell subviews do not resize

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

In most cases the works in iOS7 but not on iOS 8 auto layout problems seem to stem from the root view not being sized correctly in iOS 8, particularly when we set translatesAutoresizingMaskIntoConstraints to NO. For my views I was able to set the root view's frame in layoutSubviews (or whichever appropriate initializer that does have the correct bounds) and this resolved the issue.

在大多数情况下,iOS7中的工作,而不是iOS 8的自动布局问题,似乎源于iOS 8中的根视图没有被正确地调整大小,尤其是当我们将translatesautoresizingmaskintoconstraint设置为NO时。对于我的视图,我能够在layoutSubviews中设置根视图的框架(或者任何具有正确边界的合适的初始化器),这就解决了问题。

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

As shown in the answer above, you could also do

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

self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;

and then turn translatesAutoresizingMaskIntoConstraints back to NO before you start setting your own constraints in code.

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

Definitely hate that so much of our time is taken with these annoying gotchas.

绝对讨厌我们的时间被这些烦人的陷阱占用。

#3


0  

In my case, the problem related to constraints labeled UIView-Encapsulated-Layout-Width and UIView-Encapsulated-Layout-Height. When I removed them, everything behaved as though my view was of zero size, with everything centered on the upper left corner of the screen. When I left them in, new constraints worked as expected. I also retained the constraints labeled _UILayoutSupportConstraint.

在我的例子中,这个问题与被标记为uiview -封装- layout - width和uiview -封装- layout - height的约束有关。当我移除它们时,所有的东西都表现得好像我的视图是零大小的,所有的东西都集中在屏幕的左上角。当我把它们放进去时,新的约束就会像预期的那样工作。我还保留了名为_UILayoutSupportConstraint的约束。