自动布局问题:iOS 7与iOS8的区别

4
我正在尝试创建一个可折叠的工具栏,其操作方式如下(在运行iOS 7的设备上--为了可视化目的使用丑陋的颜色):

Toolbar behavior in iOS 7

然而,在iOS 8中运行代码时,发生了以下情况:enter image description here我已经建立了一个基于以下内容的约束系统:collapsible toolbar diagram一个居中视图(未显示)将工具栏保持在屏幕中央。一个调整大小视图被调整为折叠工具栏。调整大小视图通过尾随约束与居中视图右侧连接。一个容器视图包含工具栏的实际内容。它通过尾随约束与调整大小视图右侧连接。各种内容视图包含在容器视图中。它们没有约束。系统应用的默认约束应该是宽度、高度、顶部、左侧,这确保它们在容器视图中保持相对位置。工具栏的折叠如下实现:
- (IBAction)showLess:(id)sender {
    self.widthConstraint.constant = 50; // adjust this number for collapse / expand
    [UIView animateWithDuration:0.3 animations:^{
        [self.centeringView layoutIfNeeded]; // trigger animation
    }];
}

调整sizing view的宽度。

问题:iOS 8似乎表现得好像我已经将内容视图锚定,但事实并非如此。

我真诚地希望:

  • 解释为什么iOS 8会对给定(相当简单的)约束有如此不同的解释。
  • 指导我如何在iOS 8中获得预期的行为。

源代码在这里可用(更新版本适用于iOS 8)。

更新: 该问题已经通过Stack-overflow上的答案得到解决。基本上,正确的答案是this,但是这个答案在this answer中被很好地总结了。 iOS7和iOS8之间的区别不在于解释约束的方式,而在于更新命令如何通过视图层次结构进行传递。 当我首先在iOS 7中实现这个行为时,我注意到只有在调用layoutIfNeeded时才能正常工作,即在centering view上(即sizing view的父视图)调用。在iOS 7中,这显然会自动向下滴入视图层次结构。在iOS 8中,情况并非如此。您必须手动使其无效,使用setNeedsLayout来更新已更改其约束的视图,然后使用layoutIfNeeded来更新布局。我的更新代码中的解决方案如下:

- (IBAction)showLess:(id)sender {
    self.widthConstraint.constant = 50;
    [self.sizingView setNeedsLayout]; // *** THIS LINE IS NECESSARY TO MAKE THINGS WORK IN iOS 8
    [UIView animateWithDuration:0.3 animations:^{
        [self.sizingView layoutIfNeeded]; // trigger animation
    }];
}

我希望这能帮助其他遇到向前兼容问题的人。


我也在我的一个应用程序中看到了同样的事情。 - Zhang
1
在这个问题下添加一个正常的答案并将其标记为答案。我来这里两次,以为它没有解决,然后我读了更新。 - unom
另外,考虑接受一个解决方案。 - Iulian Onofrei
1个回答

2
问题已通过Stack-overflow的答案得到解决。基本上,正确的答案在这里,但在这个答案中得到了很好的总结。iOS7和iOS8之间的区别不在于如何解释约束,而在于更新命令是如何通过视图层次结构传递的。当我首先在iOS 7中实现行为时,我注意到只有在调用layoutIfNeeded(即在centering view上)时才能正常工作。在iOS 7中,这显然会自动向下传递视图层次结构。在iOS 8中,情况则不是这样:您必须使用setNeedsLayout手动使发生约束更改的视图失效,然后使用layoutIfNeeded更新布局。我的更新代码解决方案如下:
- (IBAction)showLess:(id)sender {
    self.widthConstraint.constant = 50;
    [self.sizingView setNeedsLayout]; // *** THIS LINE IS NECESSARY TO MAKE THINGS WORK IN iOS 8
    [UIView animateWithDuration:0.3 animations:^{
        [self.sizingView layoutIfNeeded]; // trigger animation
    }];
}

我已经更新了问题以包含答案,但针对@unmircea的回复,我也会发表单独的回答。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接