Невозможно одновременно удовлетворить ограничения iOS - PullRequest
0 голосов
/ 01 апреля 2020

У меня есть кнопка, которая ограничена в нижней части вида. Кнопка изначально скрыта до тех пор, пока элемент в табличном представлении не будет нажат. Для таблицы есть контроллер поиска, и при его нажатии I w sh заставляет кнопку перемещаться так, чтобы она всегда была над клавиатурой.

    @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()
            }
        }
    }

Используя приведенный выше код, я могу получить кнопка, появляющаяся над клавиатурой при первом ее открытии. Но когда клавиатура закрыта, кнопка не возвращается в нижнюю часть экрана. Я получаю следующую ошибку ограничения:

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.

Таким образом, кажется, что ограничение из keyboardWillShow переопределяет ограничение из keyboardDidHide. Я пытался изменить приоритеты ограничений, но это тоже не работает.

1 Ответ

1 голос
/ 01 апреля 2020

Очевидно, что вы используете SnapKit. makeConstraints добавить ограничения к существующему.

Чтобы обновить существующее ограничение, вы должны использовать updateConstraints, но вы должны привязать к той же точке,

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

Если нет возможности привязки к той же точке, вы должны очистить предыдущие ограничения и сделать некоторые новые. Вы можете сделать это одновременно, используя .remakeConstraints, но вы должны добавить все другие ограничения, такие как, толчок, трейлинг, верх

...