Как изменить ограничения автоматической компоновки после их установки при использовании constraintEqualToAnchor ()?

Я пытаюсь настроить представление с ограничениями автозапуска, используя constraintEqualToAnchor():

override func viewDidLoad() {
    super.viewDidLoad()

    let myView = UIView()
    myView.backgroundColor = UIColor.orangeColor()
    myView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(myView)

    myView.leftAnchor.constraintEqualToAnchor(view.leftAnchor).active = true
    myView.trailingAnchor.constraintEqualToAnchor(view.trailingAnchor).active = true
    myView.topAnchor.constraintEqualToAnchor(view.topAnchor).active = true
    myView.bottomAnchor.constraintEqualToAnchor(view.bottomAnchor).active = true

    /******************************************/
    /* I try to change one of the constraints */
    /******************************************/
    myView.leftAnchor.constraintEqualToAnchor(view.rightAnchor, constant: -100).active = true  
}

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

"<NSLayoutConstraint:0x7fb53a5180d0 H:|-(0)-[UIView:0x7fb53a5190b0](LTR)   (Names: '|':UIView:0x7fb53a519240 )>",
"<NSLayoutConstraint:0x7fb53a51f660 H:[UIView:0x7fb53a519240]-(-100)-[UIView:0x7fb53a5190b0](LTR)>",
"<NSLayoutConstraint:0x7fb53a711ee0 'UIView-Encapsulated-Layout-Width' H:[UIView:0x7fb53a519240(414)]>"

при использовании constraintEqualToAnchor()?, каков правильный способ изменить ограничение позже после того, как я их установил?

4 ответов


вам нужно деактивировать предыдущее ограничение при активации нового, чтобы вы не в конечном итоге ограничивали свое представление. Для этого сохраните ссылку на каждое из ограничений как свойство в своем ViewController и выберите active свойство старого ограничения на false перед созданием и активацией нового ограничения:

Swift 2.x:

class ViewController: UIViewController {
    var leftConstraint: NSLayoutConstraint?
    var trailingConstraint: NSLayoutConstraint?
    var topConstraint: NSLayoutConstraint?
    var bottomConstraint: NSLayoutConstraint?

    override func viewDidLoad() {
        super.viewDidLoad()

        let myView = UIView()
        myView.backgroundColor = UIColor.orangeColor()
        myView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(myView)

        leftConstraint = myView.leftAnchor.constraintEqualToAnchor(view.leftAnchor)
        leftConstraint?.active = true

        trailingConstraint = myView.trailingAnchor.constraintEqualToAnchor(view.trailingAnchor)
        trailingConstraint?.active = true

        topConstraint = myView.topAnchor.constraintEqualToAnchor(view.topAnchor)
        topConstraint?.active = true

        bottomConstraint = myView.bottomAnchor.constraintEqualToAnchor(view.bottomAnchor)
        bottomConstraint?.active = true

        /******************************************/
        /* I try to change one of the constraints */
        /******************************************/
        leftConstraint?.active = false
        leftConstraint = myView.leftAnchor.constraintEqualToAnchor(view.rightAnchor, constant: -100)
        leftConstraint?.active = true
    }
}

обновление Swift 3 синтаксис:

class ViewController: UIViewController {
    var leftConstraint: NSLayoutConstraint?
    var trailingConstraint: NSLayoutConstraint?
    var topConstraint: NSLayoutConstraint?
    var bottomConstraint: NSLayoutConstraint?

    override func viewDidLoad() {
        super.viewDidLoad()

        let myView = UIView()
        myView.backgroundColor = UIColor.orange
        myView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(myView)

        leftConstraint = myView.leftAnchor.constraint(equalTo: view.leftAnchor)
        leftConstraint?.isActive = true

        trailingConstraint = myView.trailingAnchor.constraint(equalTo: view.trailingAnchor)
        trailingConstraint?.isActive = true

        topConstraint = myView.topAnchor.constraint(equalTo: view.topAnchor)
        topConstraint?.isActive = true

        bottomConstraint = myView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
        bottomConstraint?.isActive = true

        /******************************************/
        /* I try to change one of the constraints */
        /******************************************/
        leftConstraint?.isActive = false
        leftConstraint = myView.leftAnchor.constraint(equalTo: view.rightAnchor, constant: -100)
        leftConstraint?.isActive = true
    }
}

вот пример объявления ограничения c который будет ссылаться позже. Мы устанавливаем новое значение константы, а затем вызываем layout на суперпанель.

myView.translatesAutoresizingMaskIntoConstraints = false

var constraints: [NSLayoutConstraint] = [
    myView.topAnchor.constraintEqualToAnchor(view.topAnchor),
    myView.leftAnchor.constraintEqualToAnchor(view.leftAnchor),
    myView.bottomAnchor.constraintEqualToAnchor(view.bottomAnchor)
]         
let c = myView.rightAnchor.constraintEqualToAnchor(view.rightAnchor)       
constraints.append(c)   

view.addSubview(myView)
NSLayoutConstraint.activateConstraints(constraints)

// Some time later
c.constant = -100
view.setNeedsLayout()

// method myView.topAnchor.constraintEqualToAnchor creates new one inactive anchor 
// and not returns exist with equal relationships     

// you can set identifier for any constraint in Interface Builder or code and find & update in code
for ( NSLayoutConstraint *c in [self.view constraintsAffectingLayoutForAxis:UILayoutConstraintAxisHorizontal] )
{
    if ( YES == [c.identifier isEqualToString:@"my.layout-constraint.id"] )
    {
        // Unlike the other properties, the constant can be modified
        // after constraint creation. 
        // Setting the constant on an existing constraint performs much better 
        // than removing the constraint and adding a new one that's exactly like 
        // the old except that it has a different constant.

        c.constant = 123;

        // if needed
        // [self.view setNeedsUpdateConstraints];

        break;
    }
}

вот пример с оператором IF, изменяющим StackView и View, когда сегментированный щелкнул:

if (sender as AnyObject).selectedSegmentIndex == 0{


        // Shrink the white view and stack view
        heightConstraintView = containerView.heightAnchor.constraint(equalToConstant: 100)
        heightConstraintView?.isActive = true

        heightConstraintStackView = stackView.heightAnchor.constraint(equalToConstant: 100)
        heightConstraintStackView?.isActive = true
    }

    else {


        // Before returning back the white view and stack view DEACTIVATE teh previous constraints
        heightConstraintView?.isActive = false
        heightConstraintStackView?.isActive = false

        // Returning back the white view and stack view to normal size
        heightConstraintView = containerView.heightAnchor.constraint(equalToConstant: 200)
        heightConstraintView?.isActive = true

        heightConstraintStackView = stackView.heightAnchor.constraint(equalToConstant: 200)
            heightConstraintStackView?.isActive = true
    }