简体   繁体   中英

How to update NSLayoutConstraint constants, that have previously been set in code? - Swift

I'm trying to completely make my view programatically. It has a bottom view that animates up when a search query finishes with the relevant information. I've set the .bottom nslayoutconstraint of the bottom view to an optional nslayoutconstraint, first initialising it off screen in 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
        ])
   }

The view appears up once the search query is complete.

                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)

However after that point, when I try to dismiss the view, and change the NsLayoutConstraint's constant, the view doesn't move.

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

In the output console, I'm getting this error and I'm not sure how to fix it.

    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)>

The problem is that your

override func viewWillLayoutSubviews() {

runs again and again and again. Layout happens a lot! Thus, those constraints all get created and added again and again, including after you have done the animation and changed the bottom constraint. So you end up with two conflicting bottom constraints. (You actually have lots of bottom constraints, but all the others are equal to one of the the conflicting constraints so the runtime doesn't complain.)

A simple solution that I like to use is to put a boolean flag so that my initial configuration only happens once:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM