更改 NSLayoutConstraint 的常量

Posted

技术标签:

【中文标题】更改 NSLayoutConstraint 的常量【英文标题】:Changing the constant of a NSLayoutConstraint 【发布时间】:2017-08-14 03:17:15 【问题描述】:

背景

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

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


现有配置

Progress Bar UIView 的约束设置为与超级视图(Progress View)齐平:

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

在 ProgressView 类中,有一个setProgress 函数。这个函数是从包含 ProgressView 的 ViewController 中调用的。下面是 cmets 的函数,解释了它是如何工作的:

 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,进度条填满整个轨道。


尝试的解决方案

我已经尝试在每个位置和配置中调用layoutIfNeeded()setNeedsLayout() (在self [其中self 是ProgressView] 和progressBar)。我尝试使用DispatchQueue.main.async 将代码显式放在主线程上。作为一个基本事实测试,我尝试将 trailingConstraint 出口连接到 ViewController 本身,并从 viewDidAppear()viewDidLayoutSubviews() 方法更新常量。没有任何效果。


正确方向的可能提示

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

我在 ios 10 设备上进行测试并运行 Xcode 8.3.3。这个问题对我来说似乎很奇怪,我不太确定从这里做什么。感谢您的帮助。

【问题讨论】:

【参考方案1】:

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

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

【讨论】:

我已经尝试了 layoutIfNeeded 和 constant 在动画外部,其中 layoutIfNeeded 内部。我已经尝试过常量和 layoutIfNeeded 里面。不幸的是,没有一个工作。 将这一行 self.trailingConstraint.constant = newConstant 放到动画块之外 你给的动画持续时间是 0.2 秒吗。试试看。这就像一种 hack @Dev_Tandel 我试过了。不幸的是没有工作。在我的 setProgress 方法中,我还在警卫内进行了非动画约束更改。那也不行。 @Arnav 我尝试了硬编码的持续时间值(2 秒)。没用。 0.2 秒会有所不同吗?

以上是关于更改 NSLayoutConstraint 的常量的主要内容,如果未能解决你的问题,请参考以下文章

NSLayoutConstraint 的 Unsatisfiable Constraint 以编程方式更改 - swift

NSLayoutConstraint 的默认常量是啥?

NSLayoutConstraint 常量没有更新

NSLayoutConstraint 不使用 UIView.animate 进行动画处理

在 iOS7 中设置 NSLayoutConstraint 常量

在 NSLayoutConstraint 上更新“常量”失败,并显示“无法分配给 'constraint' 中的 'constant'”