Безопасно изменить постоянное значение NSLayoutConstraint - PullRequest
0 голосов
/ 19 июня 2019

У меня есть нижнее ограничение для моего UIView объекта, и я хочу изменить его значение. После того, как я это сделал, представление действительно отображается правильно, но я вижу журнал ошибок в консоли;

[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:0x600003cbe670 PSBApp.KeyboardView:0x7fc5f760e010.bottom == UIView:0x7fc5f4503090.bottom + 306   (active)>",
    "<NSLayoutConstraint:0x600003c8cbe0 PSBApp.KeyboardView:0x7fc5f760e010.bottom == UIView:0x7fc5f4503090.bottom - 10   (active)>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x600003cbe670 PSBApp.KeyboardView:0x7fc5f760e010.bottom == UIView:0x7fc5f4503090.bottom + 306   (active)>

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.

Мой код:

private func setupKeyboard(){
    keyboard.delegate = self
    view.addSubview(keyboard)
    keyboardBottomConstraint = keyboard.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: keyboard.expectedHeight())
    keyboard.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    keyboardBottomConstraint.isActive = true
  }

  private func showKeyboard(){
    let bottomOffset: CGFloat = 10
    keyboardBottomConstraint.constant = -bottomOffset
  }

Итак, после того, как я setupKeyboard, на экране нет ошибки и нет видимого изображения, затем, после того, как я позвоню showKeyboard, оно становится видимым, но появляется ошибка.

Ответы [ 3 ]

1 голос
/ 19 июня 2019

Там сообщение об ошибке / предупреждение содержит ключ:

(
    "<NSLayoutConstraint:0x600003cbe670 PSBApp.KeyboardView:0x7fc5f760e010.bottom == UIView:0x7fc5f4503090.bottom + 306   (active)>",
    "<NSLayoutConstraint:0x600003c8cbe0 PSBApp.KeyboardView:0x7fc5f760e010.bottom == UIView:0x7fc5f4503090.bottom - 10   (active)>"
)

Как видите, KeyboardView имеет два нижних ограничений, которые не могут быть действительными одновременно.

Согласно комментариям ФП, setupKeyboard() был вызван по неосторожности дважды, что привело к двум нижним ограничениям.

1 голос
/ 19 июня 2019

Установить значение приоритета нижнего ограничения как Высокое (750)

0 голосов
/ 19 июня 2019

вы можете использовать layoutIfNeeded и setNeedsLayout автоматически:

layoutIfNeeded принудительно заставляет получателя немедленно размещать свои подпредставления, если это необходимо.

Предположим, у вас есть переопределенные layoutSubviews, и UIKit чувствует, что вашему представлению требуется макет по какой-либо причине (например, вы вызвали setNeedsLayout при обработке какого-либо действия пользователя). Затем ваш пользовательский метод layoutSubviews будет вызываться немедленно, а не тогда, когда он обычно вызывается в обычной последовательности событий цикла выполнения UIKit (после обработки события, но перед drawRect:).

Пример того, почему вам может потребоваться вызвать layoutIfNeeded в одном цикле выполнения:

Вы изменяете размеры настраиваемого представления, содержащего табличное представление. setNeedsLayout установлен так, что layoutSubviews будет вызываться позже. Контроллер объекта просит табличное представление прокрутить до некоторой конкретной ячейки при обработке пользовательского события. Ваше пользовательское представление выполняет некоторое пользовательское изменение размера табличного представления в layoutSubviews, которое изменяет размер табличного представления. Проблема заключается в том, что когда контроллер запросил прокрутку табличного представления (шаг 2), у табличного представления были устаревшие границы. Обновленные границы будут установлены только в табличном представлении позже (шаг 3). То, к чему контроллер хотел прокрутить табличное представление, может фактически не быть видимым после того, как layoutSubviews сделан. Тогда решение будет для контроллера вызывать layoutIfNeeded в ситуациях, когда он знает, что это может произойти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...