更改NSLayoutConstraint的常量

时间:2017-08-14 03:17:16

标签: ios swift uiview nslayoutconstraint

背景

我正在尝试使用动画和非动画选项进行相当标准的NSLayoutConstraint常量更新。为了给你一些背景知识,我有一个名为ProgressView的UIView子类。在ProgressView中,有Progress Bar UIView。 Progress Bar UIView作为引用插座progressBar连接到ProgressView类。以下是故事板中相当简单的层次结构的外观:

Storyboard hierarchy shows Progress Bar within Progress View

正如您可能已经猜到的那样,我正在构建一个自定义进度条。 ProgressView UIView是“轨道”,进度栏UIView是“填充”。计划是使用Progress Bar UIView的尾随约束来更改进度。

现有配置

Progress Bar UIView的约束设置为与superview(进度视图)齐平:

Constraints

Progress Bar UIView的尾随约束作为强大的插座连接到ProgressView类:@IBOutlet var trailingConstraint: NSLayoutConstraint!

在ProgressView类中,有一个setProgress函数。从包含ProgressView的ViewController调用此函数。这是函数,其中的注释解释了它的工作原理:

 public func setProgress(_ progress: Double, animationDuration: Double) {

    // Pre-conditions
    guard progress >= 0.0 && progress <= 1.0 && animationDuration >= 0.0 else {
        return
    }

    // Calculate the new constraint constant based on the progress
    let newConstant = CGFloat(1 - progress) * self.bounds.size.width

    // If the update should be made without animation, just make the change and return
    guard animationDuration > 0.0 else {
        trailingConstraint.constant = newConstant            
        return
    }

    // Set the constraint first
    self.trailingConstraint.constant = newConstant

    // Animate!
    UIView.animate(withDuration: animationDuration) {
        self.layoutIfNeeded()
    }

}

问题

如您所见,此功能可以使用和不使用动画来更新进度。但是,从ViewController调用时,都不起作用。尾随约束常量似乎保持为0,进度条填满整个轨道。

Filled bar

尝试解决方案

我尝试在layoutIfNeeded() [其中setNeedsLayout()是ProgressView]和{{} self的每个位置和配置中调用selfprogressBar 1}})。我已经尝试使用DispatchQueue.main.async将代码显式放在主线程上。作为基础事实测试,我尝试将trailingConstraint出口连接到ViewController本身,并从viewDidAppear()viewDidLayoutSubviews()方法更新常量。什么都行不通。

正确方向的可能提示

这是奇怪的部分。进度条显示在屏幕上,但是当我调试视图层次结构时,进度条看起来是正确的。 trailingConstraint常量似乎已正确设置。

Correct bar

Correct constraints

我在iOS 10设备上测试并运行Xcode 8.3.3。这个问题对我来说似乎很奇怪,而且我不太清楚从这里做什么。谢谢你的帮助。

1 个答案:

答案 0 :(得分:0)

我遇到了同样的问题。我的问题是通过改变动画中的常量来解决的。试试这个:

 UIView.animate(withDuration: 0.2) { 
    self.trailingConstraint.constant = newConstant
    self.layoutIfNeeded()
    }