如何更新之前在代码中设置的 NSLayoutConstraint 常量? - 斯威夫特

Posted

技术标签:

【中文标题】如何更新之前在代码中设置的 NSLayoutConstraint 常量? - 斯威夫特【英文标题】:How to update NSLayoutConstraint constants, that have previously been set in code? - Swift 【发布时间】:2016-10-11 03:52:54 【问题描述】:

我正在尝试完全以编程方式制作我的视图。它有一个底部视图,当搜索查询完成相关信息时会显示动画。我已将底部视图的 .bottom nslayoutconstraint 设置为可选的 nslayoutconstraint,首先在 override func viewWillLayoutSubviews() 中将其初始化为屏幕外。

    let bottomView = UIView()
    var bottomViewBottomConstraint: NSLayoutConstraint!

override func viewDidLoad() 
    super.viewDidLoad()
    view.addSubview(bottomView)



override func viewWillLayoutSubviews() 

    //Bottom View Constraints
    bottomView.translatesAutoresizingMaskIntoConstraints = false
    let bottomViewLeftConstraint = NSLayoutConstraint(item: bottomView, attribute: .left, relatedBy: .equal, toItem: view, attribute: .left, multiplier: 1, constant: 0)
    let bottomViewRightConstraint = NSLayoutConstraint(item: bottomView, attribute: .right, relatedBy: .equal, toItem: view, attribute: .right, multiplier: 1, constant: 0)
    let bottomViewHeightConstraint = NSLayoutConstraint(item: bottomView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 75)
    bottomViewBottomConstraint = NSLayoutConstraint(item: self.bottomView, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1, constant: 100)

    NSLayoutConstraint.activate([
        bottomViewLeftConstraint, bottomViewRightConstraint, bottomViewBottomConstraint, bottomViewHeightConstraint
        ])
   

一旦搜索查询完成,视图就会出现。

                self.view.layoutIfNeeded()

            UIView.animate(withDuration: 0.8, delay: 1, usingSpringWithDamping: 1, initialSpringVelocity: 0.1, options: .curveEaseIn, animations: 
                    self.bottomViewBottomConstraint.constant = -5
                    self.view.layoutIfNeeded()
                , completion: nil)

但是在那之后,当我尝试关闭视图并更改 NsLayoutConstraint 的常量时,视图不会移动。

    self.view.layoutIfNeeded()
    UIView.animate(withDuration: 0.8, animations: 
        self.bottomViewBottomConstraint.constant = 100
        self.view.layoutIfNeeded()
    )

在输出控制台中,我收到了这个错误,我不知道如何修复它。

    Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to      catch this in the debugger.
    The methods in the UIConstraintBasedLayoutDebugging category on UIView   listed in <UIKit/UIView.h> may also be helpful.
    2016-10-11 14:50:01.768353 Green Homes Australia[973:232019]   [LayoutConstraints] Unable to simultaneously satisfy constraints.
        Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
(
    "<NSLayoutConstraint:0x17028d6b0 UIView:0x1049365b0.bottom == UIView:0x100b04e40.bottom - 5   (active)>",
    "<NSLayoutConstraint:0x174681cc0 UIView:0x1049365b0.bottom == UIView:0x100b04e40.bottom + 100   (active)>")

    Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x174681cc0 UIView:0x1049365b0.bottom == UIView:0x100b04e40.bottom + 100   (active)>

【问题讨论】:

【参考方案1】:

问题是你的

override func viewWillLayoutSubviews() 

一次又一次地运行。布局发生了很多!因此,这些约束都会一次又一次地创建和添加,包括 您完成动画并更改底部约束之后。因此,您最终会遇到两个相互冲突的底部约束。 (您实际上有 很多 个底部约束,但所有其他约束都等于冲突约束之一,因此运行时不会抱怨。)

我喜欢使用的一个简单解决方案是放置一个布尔标志,以便我的初始配置只发生一次:

var didConfig = false
override func viewWillLayoutSubviews() 
    if !didConfig 
        didConfig = true
        // create and configure constraints here
    

【讨论】:

谢谢,你的救命稻草,以为它只在运行时运行。 即使在自定义 setup() 方法中引导约束时,我也有相同的效果和分辨率。我的类的子类覆盖了该方法并调用了super.setup(),它使用不一致的值重新引导了约束。通过将我的引导设置方法设置为private 解决,消除了多次调用。

以上是关于如何更新之前在代码中设置的 NSLayoutConstraint 常量? - 斯威夫特的主要内容,如果未能解决你的问题,请参考以下文章

如何刷新我在 ServletContextListener 中设置的 servlet 上下文变量?

如何让自定义标签栏显示标签栏项目在 Xcode 中设置的选定图像?

如何以编程方式连接到已在 Android 手机中设置的 ***

除了在hadoop集群中设置的时间之外,如何为长时间运行的应用程序更新委托令牌

以编程方式更新 WooCommerce 产品中设置的自定义属性值

在控制器中设置的用户默认值无法在控制器中读取