自动布局问题:iOS 7与iOS8

我正在尝试创建一个像这样工作的可折叠工具栏(在iOS 7中运行 – 丑陋的颜色等用于可视化目的):

但是,当我在iOS 8中运行代码时,会发生以下情况:

我已经建立了一个基于以下内容的约束系统:

中心视图(未示出)使工具栏保持在屏幕中间.
调整大小视图以折叠工具栏.大小调整视图锚定在居中视图的右侧(通过尾随约束).
容器视图包含工具栏的实际内容.它锚定在大小视图的右侧(也通过尾随约束).
容器视图中包含各种内容视图.他们没有任何限制.系统应用的默认约束应该是width,height,top,left,这可以确保它们在容器视图中保持相对位置.

工具栏的折叠如下:

- (IBAction)showLess:(id)sender {
    self.widthConstraint.constant = 50; // adjust this number for collapse / expand
    [UIView animateWithDuration:0.3 animations:^{
        [self.centeringView layoutIfNeeded]; // trigger animation
    }];
}

这会调整大小视图的宽度.

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

我真诚地感激:

>解释为什么iOS 8会对给定(相当简单)的约束进行如此完全不同的解释.
>指示我如何在iOS 8中获得预期行为的指针

Source code可用here(适用于iOS 8的更新版本).

更新:
Stack-overflow的答案解决了这个问题.基本上,正确答案是this,但它在this answer中得到了很好的总结.
iOS7和iOS8之间的区别不在于解释约束的方式,而在于更新命令通过视图层次结构向下流动的方式.
当我在iOS 7中首先实现该行为时,我注意到如果我在大小调整视图的父视图上调用layoutIfNeeded(即在居中视图上),动画将只能正常工作.在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
    }];
}

我希望这有助于其他同样坚持这种向前兼容性问题的人.

最佳答案 Stack-overflow的答案解决了这个问题.基本上,正确的答案是
this,但它在
this answer中得到了很好的总结.iOS7和iOS8之间的区别不在于解释约束的方式,而在于更新命令通过视图层次结构向下流动的方式.当我在iOS 7中首先实现该行为时,我注意到如果我在大小调整视图的父视图上调用layoutIfNeeded(即在居中视图上),动画将只能正常工作.在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,我也发布了一个单独的答案.

点赞