ios - Como posso alterar a prioridade das restrições no tempo de execução




objective-c autolayout (5)

Eu tenho uma visão que tem altura dinâmica e estou tentando alterar essa prioridade de altura da visão em tempo de execução.

Aqui está minha parte do código;

if (index == 0) {

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

} else if (index == 1) {

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

}

Estou alterando o índice com uma ação de botão. Quando executo esse código, estou recebendo este erro:

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

Qual é o meu erro aqui?


A maneira como sempre lidamos com isso é não alterar a constante de restrição, apenas a prioridade. Por exemplo, na sua situação, há duas restrições de altura.

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

se você deseja ocultar a exibição, você:

heightConstraintTwo.priority = 999;

da mesma forma, se você quiser mostrar a exibição:

heightConstraintTwo.priority = 250;

Agora você pode, basta usar a conexão IBOutlet para suas restrições e usar este código.

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

De acordo com a NSLayoutConstraints class dentro do UIKit Module

Se o nível de prioridade de uma restrição for menor que UILayoutPriorityRequired, será opcional. As restrições de prioridade mais alta são atendidas antes das restrições de prioridade mais baixa. A satisfação com restrições não é tudo ou nada. Se uma restrição 'a == b' for opcional, isso significa que tentaremos minimizar 'abs (ab)'. Esta propriedade pode ser modificada apenas como parte da configuração inicial ou quando opcional. Após a adição de uma restrição a uma exibição, uma exceção será lançada se a prioridade for alterada de / para NSLayoutPriorityRequired.

Exemplo: - restrições UIButton com várias prioridades -

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

         }  

Espero que esse cenário ajude alguém: eu tinha duas restrições, que eram opostas uma à outra, ou seja, não podiam ser satisfeitas ao mesmo tempo; no criador de interface, um deles tinha 1000 prioridades e outro com menos de 1000. quando os alterei no código, tive este erro:

Finalizando o aplicativo devido à exceção não capturada 'NSInternalInconsistencyException', motivo: 'Não há suporte para a alteração de uma prioridade de necessária para não em uma restrição instalada (ou vice-versa). Você passou na prioridade 250 e a prioridade existente era 1000. '

então eu apenas os inicializei na função viewDidLoad com os valores .defaultHigh e .defaultLow e isso corrigiu o meu problema.


Versão rápida:

myContraint.priority = UILayoutPriority(999.0)




constraints