Swiftpack.co - Package - kean/Align
Swiftpack.co is a collection of thousands of indexed Swift packages. Search packages.
Screen Shot 2020-06-15 at 23 06 32

Align introduces a better alternative to Auto Layout anchors.

  • Semantic. Align APIs focus on your goals, not the math behind Auto Layout constraints.
  • Powerful. Create multiple constraints with a single line of code.
  • Type Safe. Makes it impossible to create invalid constraints, at compile time.
  • Fluent. Concise and clear API that follows Swift API Design Guidelines.
  • Simple. Stop worrying about translatesAutoresizingMaskIntoConstraints and constraints activation.

To give you a taste of what the semantic APIs look like, here is an example:

view.anchors.edges.pin(insets: 20, alignment: .center)
pin edges with center alignmnet

Getting Started

The entire library fits in a single file with around 300 lines of code. You can simply drag-n-drop it into your app if you'd like. For more installation options, see Installation Guide.

Introduction

Anchors (Anchor<Type, Axis) represent layout attributes of a view including edges, dimensions, axis, and baselines. You use anchors to create constraints. The Align APIs fit in the following quadrant:

Core API allows you to create constraints by setting relations between one or more anchors, there APIs are similar to what NSLayoutAnchor provides. Semantic API is a high-level API that focus on your goals, such as pinning edges to the container, aligning the view, setting spacing between views, etc.

Both of these types of APIs are designed to be easily discoverable using Xcode code completions. There is also a cheat sheet available, as well as an illustrated guide located in this README.

Align Cheat Sheet

Anchors

Core API

// Align two views along one of the edges
a.anchors.leading.equal(b.anchors.leading)

// Other options are available:
// a.anchors.leading.greaterThanOrEqual(b.anchors.leading)
// a.anchors.leading.greaterThanOrEqual(b.anchors.leading, constant: 10)

// Set height to the given value (CGFloat)
a.anchors.height.equal(30)
pin edges

Align automatically sets translatesAutoresizingMaskIntoConstraints to false for every view that you manipulate using it, so you no longer have to worry about it.

Align also automatically activates the created constraints. Using (NSLayoutConstraint.active(_:) is typically slightly more efficient than activating each constraint individually. To take advantage of this method, wrap your code into Constrains initializer.

Constraints {       
    // Create constraints in this closure
}

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

Align also allows you to offset and multiply anchors. This is a lightweight operation with no allocations involved.

// Offset one of the anchors, creating a "virtual" anchor
b.anchors.leading.equal(a.anchors.trailing + 20)

// Set aspect ratio for a view
b.anchors.height.equal(a.anchors.width * 2)
pin edges

Semantic API

// Set spacing between two views
a.anchors.bottom.spacing(20, to: b.anchors.top)

// Pin an edge to the superview
a.anchors.trailing.pin(inset: 20)
pin edges
Clamps the dimension of a view to the given limiting range.
a.anchors.width.clamp(to: 40...100)
pin edges

Anchor Collections

With Align, you can manipulate multiple edges at the same time, creating more than one constraint at a time.

Edges

pin() is probably the most powerful and flexible API in Align.

view.anchors.edges.pin(insets: 20)

// Same as the following:
view.anchors.edges.pin(
    to: view.superview!
    insets: EdgeInsets(top: 20, left: 20, bottom: 20, trailing: 20),
    alignment: .fill
)
pin edges

By default, pin() method pin the edges to the superview of the current view. However, you can select any target view or layout guide:

// Pin to superview
view.anchors.edges.pin()

// Pin to layout margins guide
view.anchors.edges.pin(to: container.layoutMarginsGuide)

// Pin to safe area
view.anchors.edges.pin(to: container.safeAreaLayoutGuide)

Align also provides a convenient way to access anchors of the layout guide: view.anchors.safeArea.top.

By default, pin() users .fill alignment. There are variety of other alignments available (81 if you combine all possible options).

view.anchors.edges.pin(insets: 20, alignment: .center)
pin edges with center alignmnet

You can create constraint along the given axis.

view.anchors.edges.pin(insets: 20, axis: .horizontal, alignment: .center)
pin edges with center alignmnet for horizontal axis

Or pin the view to to a corner.

view.anchors.edges.pin(insets: 20, alignment: .topLeading)
pin edges with center alignmnet for horizontal axis

You can create custom alignments (see Alignment type) by providing a vertical and horizontal component.

anchors.edges.pin(insets: 20, alignment: Alignment(vertical: .center, horizontal: .leading))
pin edges with center alignmnet for horizontal axis

Center

a.anchors.center.align()
size equal

Size

a.anchors.size.equal(CGSize(width: 120, height: 40))

greaterThanEqual and lessThanOrEqual options are also available

size equal
a.anchors.size.equal(b)
size equal other view

Advanced

By default, Align automatically activates created constraints. Using Constraints API, constraints are activated all of the same time when you exit from the closure. It gives you a chance to change the priority of the constraints.

Constraints(for: title, subtitle) { title, subtitle in
    // Align one anchor with another
    subtitle.top.spacing(10, to: title.bottom + 10)

    // Manipulate dimensions
    title.width.equal(100)

    // Change a priority of constraints inside a group:
    subtitle.bottom.pin().priority = UILayoutPriority(999)
}

Constraints also give you easy access to Align anchors (notice, there is no .anchors call in the example). And if you want to not activate the constraints, there is an option for that:

Constraints(activate: false) {
    // Create your constraints here
}

Requirements

Align Swift Xcode Platforms
Align 2.0 Swift 5.1 Xcode 11.0 iOS 11.0 / tvOS 11.0 / macOS 10.13
Align 1.1-1.2 Swift 4.2 – 5.0 Xcode 10.1 – 10.2 iOS 10.0 / tvOS 10.0
Align 1.0 Swift 4.0 – 4.2 Xcode 9.2 – 10.1 iOS 9.0 / tvOS 9.0

Why Align

Align 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.

Align is for someone who:

  • Prefers fluent API that follows Swift API Design Guidelines
  • Doesn't want to depend on big, complex libraries
  • Prefers to have as little extensions for native classes as possible, Align only adds one property
  • Doesn't overuse operator overloads, prefers fast compile times
  • Likes NSLayoutAnchor but wishes it had simpler, more fluent API which didn't require manually activating constraints

Github

link
Stars: 242

Releases

Align 2.4.1 - 2020-06-21T17:53:09

  • Fix typo in Alignment

Align 2.4.0 - 2020-06-21T17:29:24

  • Add Cheat Sheet
  • Remove anchors.margins and anchors.safeArea APIs
  • Documentation improvements

Align 2.3 - 2020-06-21T01:53:03

This release focuses on filling the remaining gaps in the API.

  • Constraints type now conforms to Collection protocol (backed by Array)
  • Add Constraints activate() and deactivate() methods
  • Add clamp(to limit: ClosedRange<CGFloat>) API for dimension anchors
  • Add default insets argument for AnchorCollectionEdges equal method
  • Replace the target parameter of AnchorCollectionEdges equal method with LayoutItem
  • Add AnchorCollectionEdges variant that works with CGFloat
  • Add AnchorCollectionEdges lessThatOrEqual() method
  • Fix AnchorCollectionCenter lessThatOrEqual() method
  • Replace the target parameter of AnchorCollectionCenter method with LayoutItem
  • Performance optimizations

Align 2.2.1 - 2020-06-18T14:50:31

  • Add a missing version of pin() that works with CGFloat as insets

Align 2.2 - 2020-06-18T13:15:04

  • Add missing Core APIs for collections

Align 2.1 - 2020-06-18T02:12:58

Use Migraiton Guide included in the repo to ease migration.

  • Remove all deprecated APIs. If you are migrating from the previous version, consider migrating to version 2.0.0 first. It is going to guide you throught the migration.

Align 2.0 - 2020-06-18T02:00:34

Use Migraiton Guide included in the repo to ease migration.

  • Add macOS support
  • Add new low-level APIs: equal, greaterThanOrEqual, lessThatOrEqual
  • Add spacing() method for alignments
  • Rename uncler .al to .anchors
  • Remove .al version accepting closure
  • Add constraints property to Constraints type to allow access to all of the constraints created using it
  • Add activate parameter to Constraints initiliazer to optionally disable automatic activation of constraints
  • Deprecated func edges(_ edges: LayoutEdge...), use pin(axis:) insteads
  • pin() methods now use .leading and .trailing anchors intead of absolute .left and .right anchors. To switch to absolute anchors, use absolute(): view.anchors.edges.absolute()
  • Remove addSubview family of APIs
  • Migrate to Swift 5.1
  • Increase minimum required platform versions

Align 1.2.1 - 2019-09-01T06:19:12

  • Add support for Swift Package Manager 5.0

Align 1.2 - 2019-06-20T16:42:40

  • Rebrand

Align 1.1 - 2019-04-07T19:06:09

  • Add Swift 5.0 support
  • Remove Swift 4.0 and Swift 4.1 support
  • Remove iOS 9, tvOS 9 support

Align 1.0 - 2018-10-02T06:09:07

Updated to Swift 4.2 (required) and Xcode 10.

Align 0.6 - 2018-05-21T18:11:16

A minor update to make Align a bit more ergonomic.

  • Add iOS 9 and tvOS 9 compatibility (used to require iOS 10 and tvOS 10).
  • Add operators for setting multipliers: view.height.match(view.width * 2).
  • Deprecated align(with:...) and match(:...) methods which had offset and multiplier parameters. Operators are the preferred way to set those (more compact and more obvious what they mean).
  • Move phantom types (e.g. AnchorAxisVertical) into namespaces to reduce clutter in a global namespace.

Align 0.5.1 - 2018-03-02T12:06:03

  • Improve documentation
  • Improve some minor implementation details
  • Update project to Xcode 9.3 recommended settings

Align 0.5 - 2018-01-10T18:25:02

  • Remove Stacks and Spacers (gist)
  • Remove Insets

Align 0.4 - 2017-12-29T15:51:38

  • pinToSuperviewMargins methods now use margin attributes (e.g. .topMargin) and not layoutMarginsGuide to workaround issues on iOS 10 where layout guides are unpredictable https://stackoverflow.com/questions/32694124/auto-layout-layoutmarginsguide
  • Add pinToSafeArea(of:) family of methods which use safeAreaLayoutGuide on iOS 11 and fall back to topLayoutGuide and bottomLayoutGuide on iOS 10
  • addSubview methods are no longer generic which allows for more extra flexibility when adding constraints (e.g. you can create and operate on an array of layout proxies)

Align 0.3.1 - 2017-11-18T22:11:10

A small update that focuses on improving offsetting(by:) method.

  • offsetting(by:) method now available for all anchors
  • Add an operator that wraps offsetting(by:) method (which wasn't very convenient to use by itself)
  • [Fix] Offsetting anchor which already has an offset now works correctly
  • Split the project into two files

Align 0.3 - 2017-11-15T10:16:52

  • With new 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).

  • Remove standalone fillSuperview(..) and centerInSuperview() family of functions. There were multiple cons of having them (e.g. more terminology to learn, hard to document and explain, inconsistent with center and size manipulations, were not allowing to pin in a corner).

Now you can manipulate multiple edges at the same time instead:

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
}

This is a much simpler model which removes entire layer of standalone methods available on LayoutItems. Now you always select either an anchor or collections of anchors, then use their methods to add constraints. Much simpler.

  • Make LayoutProxy's base public to enable adding custom extensions on top of it.

Align 0.2 - 2017-11-13T08:28:29

  • Redesigned Align API which now follow Swift API Design Guidelines. Although most of the APIs are compact, it is a non-goal to enable the most concise syntax possible. Instead Align provides a fluent APIs that form grammatical phrases.
  • Full test coverage
  • Add a new comprehensive overview, full guide, and installation guide

Yalta 0.1.1 - 2017-11-09T17:27:57

Revert to original Spacer design.

Align 0.1 - 2017-11-09T17:27:43

Initial public version.