以编程方式修改自动布局约束时视图不更新

Posted

技术标签:

【中文标题】以编程方式修改自动布局约束时视图不更新【英文标题】:View not updating when autolayout constraint modified programmatically 【发布时间】:2014-05-30 20:29:48 【问题描述】:

在修改第二个约束(第一个工作正常)后,我无法让我的视图正确布局。我正在修改一个约束,对其进行动画处理,然后在完成块中修改另一个约束(没有动画)。

我这样做的原因是我不希望第二个约束更改影响动画,但我希望它在初始动画完成后立即生效。

问题是第二个约束更改根本没有生效,无论我尝试什么。

这是我正在尝试的(请注意,问题仅在 toolbarVisibleYES 时,因为当它为 NO 时我会预先执行两个动画):

    if ( !toolbarVisible )
        self.containerViewBottomSpace.constant = toolbarVisible ? 60.f : 0;
    self.toolbarBottomSpace.constant = toolbarVisible ? 0 : 60.f; // this one works fine
    [self.view setNeedsUpdateConstraints];
    [UIView animateWithDuration:0.3f animations:^
        [self.view layoutIfNeeded];
     completion:^(BOOL finished) 
        if ( toolbarVisible )
            self.containerViewBottomSpace.constant = 60.f; // this one is not taking effect
        [self.view setNeedsUpdateConstraints];
        [self.view layoutIfNeeded];
    ];

上述方法发生在observeValueForKeyPath:... 方法中。我尝试将上面的整个代码包装在 dispatch_after 块中,但这会产生更糟糕的效果,因为它总是落后一步(即 containerView 总是处于应有的相反位置),就好像第二个约束一样在下一个动画之前,修改不会生效。

同样,如果我将另一个视图推送到导航控制器(嵌入在 containerView 中),布局会自行纠正。就好像它只是无视我的命令,出于某种原因重新布置。

实际上,我只是注意到,即使我最初进行了第二次更改并完全跳过了完成块,它似乎并没有在所有情况下为第二次约束更改设置动画。有点可疑。

更新:我使用 dispatch_after 错误地认为它接受了 NSTimeInterval。在给它一个适当的dispatch_time_t 并将其放入完成块之后,布局现在有时会更新。但是,它非常不稳定,而且看起来很hackish,所以我觉得好像我错过了一些东西。如果有人对此了解更多,请赐教,我会给你答案。

更新 2: 我决定尝试在 viewDidLayoutSubviews 中记录我要更改的元素的高度。有趣的是,它被调用了两次,第一次使用之前的值,第二次使用正确调整的高度。所以我猜它至少 部分 正确地布置了东西,但由于某种原因,containerView 内部的 tableView 仍然没有正确调整自己的大小。我不确定我错过了什么。

【问题讨论】:

【参考方案1】:

我会先设置断点,并确保在动画持续时间内您没有第二次点击动画代码。如果它在 observeValueForKeyPath 中,您可能会多次点击动画,这会导致一些不一致。

您也不需要调用 setNeedsUpdateConstraints 或 layoutIfNeeded。设置常量就足够了。

我还要确保您已正确连接约束并且 toolbarVisible 为 true。

【讨论】:

我正在记录一些调试语句,以确保它只在预期的时候被调用一次。约束是正确连接的,因为更改最终会生效,而不是在应该的时候立即生效。例如,如果我旋转设备,它会突然正确渲染,包括我是否旋转回原始方向。

以上是关于以编程方式修改自动布局约束时视图不更新的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式添加控制器视图时自定义自动布局约束被破坏

自定义 tableviewcell 动态高度未根据约束更新(以编程方式自动布局)

以编程方式更改视图尺寸时,自动布局似乎不起作用

以编程方式添加约束会破坏自动布局约束

iOS 以编程方式生成的视图具有隐藏的约束,导致与自动布局发生冲突

自动布局 - 以编程方式定义异常约束