We've covered Auto Layout quite bit, but so far we've only been using the classes and APIs that Apple ships. Today we'll start checking out some third-party libraries that can improve our experience when working with Auto Layout.

First up is Cartography from Robert BΓΆhnke. Let's take a look:

Cartography takes the form of a sort of DSL for Auto Layout. It allows us to take conventional UIKit code like this:

view.addConstraint(
  NSLayoutConstraint(
    item: editButton,
    attribute: .Right,
    relatedBy: .Equal,
    toItem: launchButton,
    attribute: .Left,
    multiplier: 1.0,
    constant: -8.0
  )
)

And express it using a new constrain function:

constrain(editButton, launchButton) { editButton, launchButton in
  editButton.right == launchButton.left - 8
}

We can pass in up to 5 UIView or NSView instances at once, then a closure. In that closure, we'll use ==, >=, or <= operators to define constraints upon the attributes of the view instances. This can really help improve readability:

constrain(viewA) { a in
  // fixed sizes:
  a.height == 44

  // centering inside a parent view:
  a.centerX == a.superview!.centerX

  // inequalities:
  a.top >= a.superview!.top + 10
}

But wait, there's more! We can capture the created constraints like this:

let group = constrain(launchButton) { button in
  button.top  == button.superview!.top
  button.left == button.superview!.left
}

Then move that button by replacing the captured constraints like this:

constrain(launchButton, replace: group) { button in
  button.bottom == button.superview!.bottom
  button.right  == button.superview!.right
}

Additionally, it provides helper functions for aligning and distributing:

constrain(viewA, viewB, viewC) { viewA, viewB, viewC in
  align(top: viewA, viewB, viewC)
  distribute(by: 8, horizontally: viewA, viewB, viewC)
}

Cartography has shortcuts for edges and sizes, operators for setting priorities, and much more! More info can be found at git.io/cartography.