JBNSLayoutConstraint

Read about the motivation and creation of these categories.

JBNSLayoutConstraint is a set of Objective-C categories that adds string-based linear equations and installation assistance to Auto Layout constraints.

As an example, this single method creates four constraints and adds each constraint to its closest ancestor view:

[NSLayoutConstraint
    jb_installConstraintsWithVisualFormat:@"view1.center==|;view1.size==50.0"
                                  options:0
                                  metrics:nil
                                    views:@{ @"view1" : view1 }]];

Overview

JBNSLayoutConstraint+LinearEquation.h makes it easy to create constraints using a string-based linear equation of the following form:

view1.attr1 == view2.attr2 * multiplier + constant @ priority

Multiple expressions can be passed by separating them with a semicolon, and linear equations can be mixed with NSLayoutConstraint’s existing ASCII art-like visual format strings.

JBNSLayoutConstraint+Install.h adds methods to automatically install (and uninstall) one or more constraints on the closest common ancestor of each constraint’s involved views.

There are many NSLayoutConstraint categories out there, but I wanted one that allowed me to easily pass multiple visual format strings to a single method and also allowed me to express constraints using string-based linear equations. Basically, I just wanted to type less code.

Requirements

The JBNSLayoutConstraint categories have been built and tested for iOS, and they have the same requirements as Auto Layout: iOS 6.0 and later. Also, while these categories may work for Mac development (and NSView) with slight modification, I have not tried this myself.

Download

The Xcode 5 project includes a set of unit tests and a quick-and-dirty sample app that makes it easy to experiment with formats and expressions.

JBNSLayoutConstraint on Github

The sample app includes three views (view1, view2, and view3) and three metrics (metric1, metric2, and metric3). If a view has ambiguous layout (view.hasAmbiguousLayout == YES), its border will be red. Otherwise, its border is green.

JBNSLayoutConstraint+LinearEquation.h

To add string-based linear equation support to a project, simply:

#import "JBNSLayoutConstraint+LinearEquation.h"

Then, you can replace a traditional NSLayoutConstraint method like this:

[NSLayoutConstraint
    constraintWithItem:view1
             attribute:NSLayoutAttributeCenterX
             relatedBy:NSLayoutRelationEqual
                toItem:view1.superview
             attribute:NSLayoutAttributeCenterX
            multiplier:1.0f
              constant:0.0f];

…with a string-based linear equation:

[NSLayoutConstraint
    jb_constraintsWithVisualFormat:@"view1.centerX==|.centerX"
                           options:0
                           metrics:nil
                             views:@{ @"view1" : view1 }];

Like Auto Layout’s visual format, the pipe character (|) references the view’s superview.

While this isolated example isn’t much shorter, the true power of the category can be seen when creating multiple constraints:

[NSLayoutConstraint
    jb_constraintsWithVisualFormat:@"view1.center==|;view1.size==50"
                           options:0
                           metrics:nil
                             views:@{ @"view1" : view1 }];

This example uses two of the three compound attributes that are included with the category: center, frame, and size. These compound attributes are automatically expanded to include an appropriate set of constraints. In this example, center expands to include attributes for both centerX and centerY, and size expands to width and height.

Also note that the second center attribute in the first expression has been omitted, because both attributes of the constraint are the same.

As mentioned, linear equations can be mixed with Auto Layout’s visual format to pass multiple expression types:

[NSLayoutConstraint
    jb_constraintsWithVisualFormat:@"H:|[view1(20)];V:|[view1];view1.height==metric1"
                           options:0
                           metrics:@{ @"metric1" : @(42) },
                             views:@{ @"view1"   : view1 }];

Compound Attributes

The three compound attributes expand to include multiple constraints (in these orders):

  • center expands to: centerX, centerY
  • size expands to: width, height
  • frame expands to: top, left, bottom, right

JBNSLayoutConstraint+Install.h

To install and uninstall one or more constraints, first:

#import "JBNSLayoutConstraint+Install.h"

Then, to install a constraint on the closest common ancestor of its involved views:

NSLayoutConstraint *constraint = ...;
[constraint jb_install];

Note that this also sets translatesAutoresizingMaskIntoConstraints to NO for the involved views.

To uninstall a constraint:

[constraint jb_uninstall];

To install multiple constraints, each to the closest common ancestor of its involved views:

NSArray *constraints = [NSLayoutConstraint jb_constraintsWithVisualFormat:...];
[NSLayoutConstraint jb_installConstraints:constraints];

Like jb_install, this sets translatesAutoresizingMaskIntoConstraints to NO for the involved views of each constraint.

Similarly, to uninstall multiple constraints:

[NSLayoutConstraint jb_uninstallConstraints:constraints];

Finally, to generate and install multiple constraints in a single call:

[NSLayoutConstraint
    jb_installConstraintsWithVisualFormat:@"view1.centerX==|"
                                  options:0
                                  metrics:nil
                                    views:@{ @"view1" : view1 }];

Feedback

As always, I’d love your feedback.