简体   繁体   中英

Unable to simultaneously satisfy constraints iOS

I have a button that is constrained to the bottom of the view. The button is initially hidden until an item in the table view is tapped. There is a search controller for the table and when this is tapped I wish to make the button move so that it is always above the keyboard.

    @objc func keyboardWillShow(notification: NSNotification) {
        if let keyboardHeight = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.height {

            startAssessmentBtn.snp.makeConstraints { make in
                make.bottom.equalTo(-keyboardHeight)
            }

            let userInfo = notification.userInfo! as [AnyHashable: Any]
            let animationDuration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as! NSNumber
            let animationCurve = userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as! NSNumber

            UIView.setAnimationCurve(UIView.AnimationCurve(rawValue: animationCurve.intValue)!)
            UIView.animate(withDuration: animationDuration.doubleValue) {
                self.tableView.setBottomInset(to: keyboardHeight)
                self.view.layoutIfNeeded()
            }
        }
    }

    @objc func keyboardDidHide(notification: NSNotification) {
        if let keyboardHeight = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {

            let userInfo = notification.userInfo! as [AnyHashable: Any]
            let animationDuration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as! NSNumber
            let animationCurve = userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as! NSNumber

            startAssessmentBtn.snp.makeConstraints { make in
                make.bottom.equalTo(0)
                //make.bottom.equalToSuperview()//.offset(+keyboardHeight)
            }

            UIView.setAnimationCurve(UIView.AnimationCurve(rawValue: animationCurve.intValue)!)
            UIView.animate(withDuration: animationDuration.doubleValue) {
                self.tableView.setBottomInset(to: 0.0)
                self.startAssessmentBtn.setNeedsLayout()
                self.startAssessmentBtn.layoutIfNeeded()
                self.view.layoutIfNeeded()
            }
        }
    }

Using the above code, I can get the button to appear above the keyboard when the keyboard is first opened. But when the keyboard is closed, the button does not return to the bottom of the screen. I get the following constraint error:

2020-04-01 17:38:42.629598+0100 AuditComply 2.0[4550:3372130] [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. 
(
    "<SnapKit.LayoutConstraint:0x2830057a0@AssetTreeViewController.swift#126 UIButton:0x121deacd0.bottom == UIView:0x121deb100.bottom - 320.0>",
    "<SnapKit.LayoutConstraint:0x283005620@AssetTreeViewController.swift#149 UIButton:0x121deacd0.bottom == UIView:0x121deb100.bottom>"
)

Will attempt to recover by breaking constraint 
<SnapKit.LayoutConstraint:0x283005620@AssetTreeViewController.swift#149 UIButton:0x121deacd0.bottom == UIView:0x121deb100.bottom>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.

So it appears the constraint from keyboardWillShow is overriding the one from keyboardDidHide. I have tried changing the priorities of the constraints but this doesn't work either.

It's obvious you're using SnapKit. makeConstraints add constraints to an existing one.

To update existing constraint you should use updateConstraints , but you should to anchor to same point,

ex: .equalToSuperview().inset(0) and .equalToSuperview().inset(keyboardHeight)

If there is no option to anchor to same point, you should clear previous constraints and make some new. You can do it simultaneously using .remakeConstraints , but you should add all other constraints, like leading, trailing, top

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