Подтвердить что ты не робот

Как изменить приоритет ограничений во время выполнения

У меня есть представление с динамической высотой, и я пытаюсь изменить этот приоритет высоты представления во время выполнения.

Вот моя часть кода;

if (index == 0) {

    surveyViewHeightConstraint.constant = 0;
    surveyViewHeightConstraint.priority = 1000;

} else if (index == 1) {

    surveyViewHeightConstraint.constant = 163;
    surveyViewHeightConstraint.priority = 500;

}

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

*** Assertion failure in -[NSLayoutConstraint setPriority:], /SourceCache/Foundation/Foundation-1141.1/Layout.subproj/NSLayoutConstraint.m:174

В чем моя ошибка?

4b9b3361

Ответ 1

Как указано в NSLayoutConstraint ссылка на класс:

Приоритеты не могут изменяться от необслуживаемых до требуемых или от требуемых до необслуживаемых. Исключение будет выбрано, если приоритет NSLayoutPriorityRequired в OS X или UILayoutPriorityRequired в iOS будет изменен на более низкий приоритет или если более низкий приоритет будет изменен на требуемый приоритет после добавления ограничений в представление. Переход от одного необязательного приоритета к другому необязательному приоритету разрешен даже после того, как ограничение установлено в представлении.

Используйте приоритет 999 вместо 1000. Это не будет абсолютно необходимо технически, но это будет более высокий приоритет, чем что-либо еще.

Ответ 2

Я хочу сделать небольшое дополнение к ответу Кирилла.

Если вы создаете ограничение в коде, не забудьте установить его приоритет, прежде чем активировать его. Например:

surveyViewHeightConstraint = [NSLayoutConstraint constraintWithItem:self
                                               attribute:NSLayoutAttributeHeight
                                               relatedBy:NSLayoutRelationEqual
                                                  toItem:self.superview
                                               attribute:NSLayoutAttributeHeight
                                              multiplier:1
                                                constant:0];
surveyViewHeightConstraint.active = YES;
surveyViewHeightConstraint.priority = 999;

Это приведет к исключению во время выполнения.

Отключение приоритета от требуемого до не установленного ограничения (или наоборот) не поддерживается.

Правильный порядок:

surveyViewHeightConstraint.priority = 999;
surveyViewHeightConstraint.active = YES;

Ответ 3

То, как мы всегда справлялись с этим, - это не изменение константы ограничения, а только приоритет. Например, в вашей ситуации есть два ограничения по высоте.

 heightConstraintOne (who height is set in the storyboard at 150, and priority set at 750)
 heightConstraintTwo (who height is set in the storyboard at 0, and priority set at 250)

если вы хотите скрыть представление, вы:

heightConstraintTwo.priority = 999;

Аналогично, если вы хотите показать представление:

heightConstraintTwo.priority = 250;

Ответ 4

Swift версия:

myContraint.priority = UILayoutPriority(999.0)

Ответ 5

Согласно NSLayoutConstraints class внутри UIKit Module

Если уровень приоритета ограничения меньше, чем UILayoutPriorityRequired, то это необязательно. Более высокий приоритет ограничения выполняются перед ограничениями с более низким приоритетом.      Удовлетворение ограничений - это не все или ничего. Если ограничение "a == b" является необязательным, это означает, что мы попытаемся свести к минимуму 'Абс (а-б).      Это свойство может быть изменено только как часть первоначальной настройки или по выбору. После того как ограничение добавлено в представление, исключение будет выбрано, если приоритет будет изменен с/на NSLayoutPriorityRequired.

Пример: - UIButton ограничения с различными приоритетами -

 func setConstraints() {
        buttonMessage.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint(item: buttonMessage, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1.0, constant: -10).isActive = true

        let leading = NSLayoutConstraint(item: buttonMessage, attribute: .leading, relatedBy: .equal, toItem: view, attribute: .leading, multiplier: 1.0, constant: 10)

        leading.isActive = true


        let widthConstraint = NSLayoutConstraint(item: buttonMessage, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 100)

        let heightConstraint = NSLayoutConstraint(item: buttonMessage, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 50)


        let trailingToSuperView = NSLayoutConstraint(item: buttonMessage, attribute: .trailing, relatedBy: .equal, toItem: view, attribute: .trailing, multiplier: 1, constant: 0)

        trailingToSuperView.priority = 999
        trailingToSuperView.isActive = true

        //leading.isActive = false//uncomment & check it will align to right of the View

        buttonMessage.addConstraints([widthConstraint,heightConstraint])

         }  

Ответ 6

Теперь вы можете просто взять соединение IBOutlet для ваших ограничений, а затем использовать этот код.

self.webviewHeight.priority = UILayoutPriority(rawValue: 1000)

Ответ 7

Я надеюсь, что этот сценарий поможет кому-то: у меня было два ограничения: они были противоположны друг другу, я имею в виду, что они не могли быть удовлетворены в одно и то же время, в конструкторе интерфейсов один из них имел приоритет 1000, а другой имел приоритет менее 1000. когда я изменил их в коде, у меня была эта ошибка:

Завершение приложения из-за невыполненного исключения "NSInternalInconsistencyException", причина: "Изменение приоритета от обязательного к отсутствию установленного ограничения (или наоборот) не поддерживается. Вы передали приоритет 250, а существующий приоритет был 1000. '

затем я просто инициализировал их в функции viewDidLoad со значениями .defaultHigh и .defaultLow, и это решило мою проблему.