Yalta is an intuitive and powerful Auto Layout library. Designed to be simple and safe, Yalta is perfect for both new and seasoned developers.

If you’d like to learn about why it exists, who is it for, and why it might be the best tool for you, please continue. The best place to start using it is in a Playground available in the project. It’s going to feel instantly familiar!

Why

The primary motivation for releasing Yalta was Chris Eidhof’s article in which he shares his concerns about the current state of Auto Layout tools in Swift. When I was deciding how to work with Auto Layout in my recent Swift project I came to the same conclusions as Chris did. Among the tools that I’ve investigated were:

  • PureLayout which I used in my Objective-C projects before. It was a great library in the Objective-C world, but even then it wasn’t the one with the most concise syntax. In Swift it became even more apparent.
  • Cartography, SnapKit. Both are pretty large and complex libraries. Operator overloads come with a good chance of increasing the app’s compile time.
  • Apple’s NSLayoutAnchor API was created in the Objective-C era. I really like the idea behind anchors, but the actual API is verbose, requires manually activating each constraint, and there is no API for creating multiple constraints at once.

So rather then pulling in a library I decided to write my own. The goal was to hit a balance between power and simplicity. I felt like I had a pretty good chance of achieving that. After all, I already had plenty of experience working with Auto Layout. The first time we adopted it in our projects was back in iOS 6 days. More recently I made Arranged (UIStackView backport) and wrote about UIStackView under the hood. I had a good idea of I wanted from this tool.

⛵Yalta

Yalta has quite a few advantages over other frameworks.

  • Yalta strives for clarity and simplicity by following Swift API Design Guidelines. Although most of the APIs are compact, it is a non-goal to enable the most concise syntax possible.
  • Yalta has a fluent API that makes use sites form grammatical English phrases. That’s what makes Swift code really stand out for me.
  • It’s extremely small and simple with less than 250 line of code (compare with 1000 lines over 27 files in Cartography).
  • There are no custom operators and thus no unexpected surprises like an increasing in your app’s compile time.
  • Yalta is designed to be approachable by new developers which benefit seasoned ones as well.

Yalta is a beautiful port city on the Black Sea and a great name for yet another layout tool with anchors.

Quick Overview

Stack and Spacers

UIStackView is king when it comes to aligning and distributing multiple views at the same time. Yalta doesn’t try to compete with stacks - it complements them:

// There are two concise ways to create stack in Yalta:
let labels = Stack([title, subtitle], axis: .vertical)
let stack = Stack(image, labels) {
    $0.spacing = 15
    $0.alignment = .top
}

// You also get convenient Spacers (including flexible ones):
Stack(title, Spacer(minWidth: 16), subtitle) // alt syntax

Check out Let’s Build UIStackView to learn how stacks work under the hood (it’s constraints all the way down).

Anchors

It’s time to add a stack to a view hierarchy and lay it out. In Yalta you start by selecting an anchor or a collection of anchors of a view (or a layout guide). Then use anchor’s methods to create constraints.

Anchors represent layout attributes of a view including edges, dimensions, axis and baselines.

The best way to access anchors is by using a special addSubview(_:constraints:) method (supports up to 4 views):

view.addSubview(stack) {
    $0.edges.pinToSuperview() // pins the edges to fill the superview
    $0.edges.pinToSuperview(insets: Insets(10)) // with insets
    $0.edges.pinToSuperviewMargins() // or margins

    $0.edges(.left, .right).pinToSuperview() // fill along horizontal axis
    $0.centerY.alignWithSuperview() // center along vertical axis
}

With addSubview(_:constraints:) method you define a view hierarchy and layout views at the same time. It encourages splitting layout code into logical blocks and prevents programmer errors (e.g. trying to add constraints to views not in view hierarchy).

Each anchor and collection of anchors have methods which make sense for that particular kind of anchor:

view.addSubview(title, subtitle) { title, subtitle in
    subtitle.top.align(with: title.bottom, offset: 10)

    title.centerX.alignWithSuperview()

    title.width.set(100)
    subtitle.width.match(title.width)

    // You can change a priority of constraints inside a group:
    subtitle.bottom.pinToSuperview().priority = UILayoutPriority(999)
}

title.al.top.pinToSuperview() // all anchors are also accessible via `.al` proxy

In addition to addSubview(_:constraints:) method there is a Constraints type which allows you to operate on an existing view hierarchy:

Constraints(for: a, b) { a, b in
    a.center.align(with: b.center)
    a.size.match(b.size)
}

Yalta has full test coverage. If you’d like to learn about which constraints (NSLayoutConstraint) Yalta creates each time you call one of its methods, test cases are a great place to start.