# Cartography :iphone::triangular_ruler: Using Cartography, you can set up your Auto Layout constraints in declarative code and without any stringly typing! In short, it allows you to replace this: ```Swift addConstraint(NSLayoutConstraint( item: button1, attribute: .Right, relatedBy: .Equal, toItem: button2, attribute: .Left, multiplier: 1.0, constant: -12.0 )) ``` with this ```Swift constrain(button1, button2) { button1, button2 in button1.right == button2.left - 12 } ``` If you end up using Cartography in production, I'd love to hear from you. You can reach me through [Twitter] or [email]. ## Installation ### CocoaPods To integrate Cartography into your Xcode project using CocoaPods, specify it in your `Podfile`: ```ruby target '' do pod 'Cartography', '~> 3.0' end ``` Then, run the following command: ```bash $ pod install ``` ## Usage Call the `constrain` function with your `UIView` or `NSView` instances as well as a closure in which you declare the constraints between the different attributes of your views: ```swift constrain(view1, view2) { view1, view2 in view1.width == (view1.superview!.width - 50) * 0.5 view2.width == view1.width - 50 view1.height == 40 view2.height == view1.height view1.centerX == view1.superview!.centerX view2.centerX == view1.centerX view1.top >= view1.superview!.top + 20 view2.top == view1.bottom + 20 } ``` For every view on the left hand side of an equality or inequality operator, Cartography will automatically set its `translatesAutoresizingMaskIntoConstraints` property to `false`. If the view is not controlled by you–for example _if it belongs to a Apple-provided `UIViewController` class_–you should take appropriate care when declaring its constraints.

## Replacing constraints You can capture multiple constraints in a group to then replace them with new constraints at a later point. ```swift constrain(view) { view in view.width == 100 view.height == 100 } let group = ConstraintGroup() // Attach `view` to the top left corner of its superview constrain(view, replace: group) { view in view.top == view.superview!.top view.left == view.superview!.left } /* Later */ // Move the view to the bottom right corner of its superview constrain(view, replace: group) { view in view.bottom == view.superview!.bottom view.right == view.superview!.right } UIView.animate(withDuration: 0.5, animations: view.layoutIfNeeded) ``` For convenience, the `constrain` functions also returns `ConstraintGroup` instances: ```swift let group = constrain(button) { button in button.width == 100 button.height == 400 } ``` ## Supported attributes Cartography supports all built-in attributes as of iOS 8 and OS X 10.9, those are: - `width` - `height` - `top` - `right` - `bottom` - `left` - `leading` - `trailing` - `centerX` - `centerY` - `baseline` as well as the iOS specific - `firstBaseline` - `leftMargin` - `rightMargin` - `topMargin` - `bottomMargin` - `leadingMargin` - `trailingMargin` - `centerXWithinMargins` - `centerYWithinMargins` - `edgesWithinMargins` These can be further refined using the following operators: `*`, `/`, `+` and `-`. Additionally, it supports convenient compound attributes that allow you to assign multiple attributes at once: ```swift constrain(view) { view in view.size == view.superview!.size / 2 view.center == view.superview!.center } ``` ```swift constrain(view) { view in view.edges == inset(view.superview!.edges, 20, 20, 40, 20) } ``` ### Aligning multiple view If you need to align multiple views by a common edge, you can use the `align` functions: ```swift constrain(view1, view2, view3) { view1, view2, view3 in align(top: view1, view2, view3) } ``` Which is equivalent to `view1.top == view2.top; view2.top == view3.top`. Similar variants exist for `top`, `right` `bottom`, `left`, `leading`, `trailing`, `centerX`, `centerY` and `baseline`. ### Distributing views evenly For distributing multiple views, either horizontally or vertically, you can use the `distribute` functions: ```swift constrain(view1, view2, view3) { view1, view2, view3 in distribute(by: 10, horizontally: view1, view2, view3) } ``` Which is equivalent to `view1.trailing == view2.leading - 10; view2.trailing == view3.leading - 10`. ## Setting priorities You can set the priorities of your constraints using the `~` operator: ```swift constrain(view) { view in view.width >= 200 ~ UILayoutPriority(100) view.height >= 200 ~ .required } ``` ## Capturing constraints Since the `==`, `>=`, `<=` and `~` emit `NSLayoutConstraint` instances, you can capture their results if you need to refer to the layout constraints at a later time: ```swift var width: NSLayoutConstraint? constrain(view) { view in width = (view.width == 200 ~ 100) } ``` Note that declaring compound attributes returns multiple constraints at once: ```swift var constraints: [NSLayoutConstraint]? constrain(view) { view in constraints = (view.size == view.superview!.size ~ .defaultLow) } ``` ## Documentation Read the documentation [here](http://robb.github.io/Cartography/). For more information, see the [gh-pages](https://github.com/robb/Cartography/tree/gh-pages) branch. ## Versioning For *Swift 3.x*: Versions <= 1.1.0 For *Swift 4.x*: Versions >= 2.0.0 For *Swift 5.x*: Versions >= 4.0.0 ## Support Please, don't hesitate to [file an issue](https://github.com/robb/Cartography/issues/new) if you have questions. ## About Cartography Cartography was built by [Robb Böhnke][me], is maintained by [Orta Therox][ot] and was inspired by the excellent [FLKAutoLayout] by [Florian Kugler][florian]. [flkautolayout]: https://github.com/floriankugler/FLKAutoLayout [florian]: https://github.com/floriankugler [me]: http://robb.is [twitter]: https://twitter.com/dlx [email]: mailto:robb@robb.is [ot]: https://github.com/orta