Orion Edwards Orion Edwards - 1 month ago 7
iOS Question

iOS constraint style: addConstraints vs .isActive = true

I have some code which is creating auto-layout constraints programatically, and adding them to a view.

There are two ways to do this - call

addConstraints
on the superView, or set
.isActive = true
on each constraint (which internally calls addConstraint)

Option 1:

parent.addConstraints([
child.topAnchor.constraint(equalTo: parent.topAnchor, constant: 20),
child.leftAnchor.constraint(equalTo: parent.leftAnchor, constant: 5) ])


Option 2:

child.topAnchor.constraint(equalTo: parent.topAnchor, constant: 20).isActive = true
child.leftAnchor.constraint(equalTo: parent.leftAnchor, constant: 5).isActive = true


My question is, is there any benefit to doing one over the other? (performance/etc) or does it come purely down to style.

(I don't think constraints are evaluated until the next layout pass, so I don't think it should matter that we add them one-by-one instead of in a block??)

If it is just style, what's the "more preferred" style by the community??

(personally I prefer addConstraints, however it's very close and I could be easily swayed to .isActive)

Answer

According to the documentation on addConstraint: setting the active property is recommended for individual constraints. (note: active property is only available iOS 8+).

When developing for iOS 8.0 or later, set the constraint’s active property to YES instead of calling the addConstraint: method directly. The active property automatically adds and removes the constraint from the correct view. (reference)

Also if you look at the interface definition for addConstraint: it has this comment:

// This method will be deprecated in a future release and should be avoided.  Instead, set NSLayoutConstraint's active property to YES


With that being said, there is actually a 3rd [and probably better] alternative, which is to use NSLayoutConstraint's class method activateConstraints::

NSLayoutConstraint.activateConstraints([
    child.topAnchor.constraint(equalTo: parent.topAnchor, constant: 20),
    child.leftAnchor.constraint(equalTo: parent.leftAnchor, constant: 5) ])

This is also a recommended solution according to the documentation and interface files. So if you have multiple constraints, this would be an easy solution and probably preferred in your situation.

(interface comment; emphasis mine):

Convenience method that activates each constraint in the contained array, in the same manner as setting active=YES. This is often more efficient than activating each constraint individually.

Comments