KeepLayout: Auto Layout constraints written as attributes on a view
Making Auto Layout easier to code.
At a glance
- What is it?
- An Objective-C library that replaces Interface Builder and Visual Format with a chainable attribute API over UIView and NSView, where constraints are created lazily, deactivatable as atomic groups, and swappable in a single animation block.
- Who is it for?
- Adopt KeepLayout if you build iOS or macOS interfaces in code and want readable constraints that can be deactivated and swapped as a unit rather than tracked by identifier. Do not adopt it if your team has standardised on SwiftUI or on a different constraint helper already, or if you need the layout guarantees of a tool that has been proven against current OS releases.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 131 days ago.
- What is it written in?
- Mainly Objective-C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Constraints become properties of the view that owns them
KeepLayout is a wrapper over Auto Layout that changes where constraints live. Instead of building an NSLayoutConstraint and activating it, you reach into a view and ask for an attribute. The library states its goal plainly: Auto Layout is easier from code, with no Interface Builder and no Visual Format, and it provides a simple, more readable API for creating and accessing existing constraints.
The API shape is two declarations per attribute:
@property (readonly) KeepLayout *keep<AttributeName>;
@property (readonly) KeepLayout *(^keep<AttributeName>To)(UIView *)); // Returns block taking another view.In practice, a view exposes named attributes such as `keepWidth`, `keepHeight`, `keepTopInset`, `keepHorizontal`, `keepLeftAlignTo` and `keepTopOffsetTo`. The second form takes another view and returns the block that yields the actual attribute, which is how offsets and alignments between two views are expressed.
The documentation is explicit that the attribute object is created on first access and that later calls return the same object. That matters for the way the library is used: `view.keepWidth` is a stable handle you can configure repeatedly, not a fresh constraint each time you touch it.
The same constraint is reachable from either side
Attributes relating two views are canonical per pair of views, and the documentation gives the two equivalences that make this concrete:
// aligns are the same regardless of order
viewOne.keepLeftAlign(viewTwo) == viewTwo.keepLeftAlign(viewOne)
// left offset from 1 to 2 is right offset from 2 to 1
viewOne.keepLeftOffset(viewTwo) == viewTwo.keepRightOffset(viewOne)An alignment is symmetric, so asking for the left alignment of one view to another and asking for it in reverse return the same underlying object. Offsets are not symmetric in wording but are in fact: the left offset from the first view to the second is the right offset from the second to the first. That is a small piece of API design that removes a class of duplicate-constraint bugs, since a second constraint created from the reverse direction would otherwise be a redundant, conflicting constraint on the same pair.
The attribute catalogue is broad. Dimensions cover width, height and aspect ratio. Insets to the superview cover top, bottom, left and right, as do insets to the superview margins. Position in the superview is expressed as horizontal and vertical. Offsets to other views cover the four edges, and alignments with other views cover the four edges plus horizontal and vertical plus first and last baselines.
The header files the documentation points to for the details are `KeepView.h`, `KeepTypes.h` and `KeepAttribute.h`.
Values carry a priority instead of being plain scalars
Every attribute has three properties, equal, min and max, and the design decision is that they are not plain numbers but values with an associated priority. Priority is Required by default, and the library supplies macros for the common levels plus an arbitrary one:
KeepValue value = 42; // value 42 at priority 1000
value = 42 +keepHigh; // value 42 at priority 750
value = 42 +keepLow; // value 42 at priority 250
value = 42 +keepFitting; // value 42 at priority 50
// Arbitrary priority:
value = 42 +keepAt(800); // value 42 at priority 800The priorities are redeclared as `KeepPriority` using `UILayoutPriority` values, with the ordering Required above High above Low above Fitting, at 1000, 750, 250 and 50 respectively.
This is where the library earns its keep in a real code base. In plain Auto Layout, expressing a value with a non default priority takes a separate constraint object with a priority set on it, and reading that code back tells you nothing about which value is which. Here the priority travels with the value, so `keepWidth.min = 320 +keepHigh` reads as one intention rather than two coupled statements.
The basic usages are short. Setting a width of 150 is `view.keepWidth.equal = 150`, and requiring a minimum top inset of 10 to the superview is `view.keepTopInset.min = 10`.
Atomic groups turn a layout into something you can switch off
The idea that distinguishes this library from a thin constraint wrapper is the atomic group. It is a way to deactivate multiple attributes at once, so that one desired set of constraints can be swapped for another:
// Create atomic group
KeepAtomic *layout = [KeepAtomic layout:^{
self.view.keepWidth.min = 320 +keepHigh; // Set minimum width limit.
self.view.keepVerticalInsets.equal = 0; // Vertically stretch to fit.
}];
[layout deactivate];
// self.view no longer has minimum width of 320 and is no longer stretched vertically.You can also deactivate a single attribute manually, by assigning `KeepNone` to one of its three properties, which removes that specific constraint, or by calling `deactivate` on the attribute, which removes all constraints for that attribute.
Grouped attributes cover the other half of the same problem, the case where several attributes should share a value. You can build a group yourself, and there are accessors for the most common ones:
KeepAttribute *leftInsets = [KeepAttribute group:
viewOne.keepLeftInset,
viewTwo.keepLeftInset,
viewThree.keepLeftInset,
nil];
leftInsets.equal = 10;view.keepSize // group of both Width and Height
view.keepInsets // group of all four insets
view.keepCenter // group of both axis of position
view.keepEdgeAlignTo // group of alignments to all four edgesCombined with the atomic group, the pattern that emerges is a set of named layouts you activate and deactivate rather than a pile of constraints you add and remove one by one. That is the case Auto Layout code usually does badly.
Arrays of views create the constraints you would otherwise write by hand
Most of the methods added to the UIView and NSView classes can also be called on an array of views, and such a call creates a grouped attribute of all the contained views' attributes:
NSArray *views = @[ viewOne, viewTwo, viewThree ];
views.keepInsets.min = 10;The documentation comments on this with emphasis: that single line creates and configures 12 layout constraints. Three views, four insets each, one assignment.
Arrays also expose relationship helpers, so you express a relationship between siblings once rather than pairing them up yourself:
NSArray *views = @[ viewOne, viewTwo, viewThree ];
[views keepWidthsEqual];
[views keepHorizontalOffsets:20];
[views keepTopAligned];The documentation points out that this created 6 new layout constraints, which is again the count of something you would otherwise write out explicitly. The category that provides this is `NSArray+KeepLayout.h`.
There is also a set of one-off convenience methods for the most common cases, described as nothing you could write yourself but which simplify code and improve readability, such as `keepSize:` with a CGSize, `keepInsets:` with a UIEdgeInsets, and `keepCentered`.
Animation and layout guides round out the API
Constraints can be animated. The documentation describes the manual route first: you can use a plain UIView block animation, but you must call `layoutIfNeeded` at the end of the animation block, which triggers `layoutSubviews` and applies the new constraints.
The library offers a wrapper so you do not have to remember that:
view.keepWidth.equal = 100;
[view.superview keepAnimatedWithDuration:1 layout:^{
view.keepWidth.equal = 200;
}];Two constraints on that method are worth noting. It is an instance method that must be called on the parent view of all affected subviews, and at the end of the layout block the receiving view receives `layoutIfNeeded`. Changes to views outside the receiver's subview tree will not be animated, which is a straightforward consequence of how UIKit animation works and is documented rather than worked around.
Spring animation from iOS 7 is included, while animations on OS X are stated as not supported yet.
The documentation also introduces layout guides: KeepLayout adds a lazy-loaded invisible `keepLayoutView` to every `UIViewControll...`, where the text is cut off. The visible part establishes the idea, that the library injects its own guide views rather than leaving you to manage anchors and guides yourself, but the details of that behaviour are not readable in the documentation shown.
Packaging, project status and what to check before adopting
The repository layout is small and conventional for a pod: a `KeepLayout.podspec` for CocoaPods, an `Example AppKit/` directory and an `Example/` directory holding a small iOS demo app, a `Sources/` directory with the library code, an Xcode project named `Keep Layout.xcodeproj`, and an Info.plist. The Example app is written in Objective-C with a prefix header and a list view controller that appears to link to the individual examples, which matches the documentation's pointer to the Examples app included in the project.
The primary language is Objective-C, and the documentation says Swift is fully supported with the usage syntax mostly the same. For a team starting a new iOS project today that raises the obvious question about long term direction, since the code base is Objective-C and the ecosystem has moved on.
On project status the documentation makes a strong claim: all planned features are implemented and functional, the project is maintained and kept up to date with the latest iOS and OS X, and issues and pull requests are welcome. The repository is not archived and the last push was on 2026-06-14, so that claim is consistent with the visible facts, though there are no GitHub releases to date the work, and the podspec rather than a tagged version is what you would pin against.
The licence is MIT, with LICENSE.md at the repository root.
The honest counterweight is that this is a small Objective-C library whose own documentation calls it maintained rather than showing a recent release history. If you are starting greenfield iOS work, the comparison to make is not with other Auto Layout helpers but with not writing code at all, because SwiftUI and, for existing UIKit code, the constraint patterns Apple ships. KeepLayout's case is strongest in an existing Objective-C codebase where a large interface is written in code and constraints have become unreadable.
Editorial conclusion
Adopt KeepLayout if you build iOS or macOS interfaces in code and want readable constraints that can be deactivated and swapped as a unit rather than tracked by identifier. Do not adopt it if your team has standardised on SwiftUI or on a different constraint helper already, or if you need the layout guarantees of a tool that has been proven against current OS releases. Verify first that the version you pull compiles against your deployment target, since the repository was last pushed on 2026-06-14 and carries no GitHub releases, and read Sources/ for the header files the documentation points to, KeepView.h and KeepAttribute.h.
Frequently asked questions
What does KeepLayout replace in Auto Layout?
It is meant to replace Interface Builder and Visual Format. Constraints are created and accessed as attributes on the UIView or NSView object rather than as separate constraint objects you build and activate.
How do I set a constraint priority in KeepLayout?
Priorities travel with the value. You add one of the supplied macros to a numeric value, for example `42 +keepHigh` for priority 750, `42 +keepLow` for 250, `42 +keepFitting` for 50, or `42 +keepAt(800)` for an arbitrary priority. The default priority is Required.
What is an atomic group in KeepLayout?
It is a way to deactivate multiple attributes at once, so one set of constraints can be swapped for another. You create it with `[KeepAtomic layout:^{...}]` and remove it with `[layout deactivate]`, after which the views no longer carry those constraints.
Does KeepLayout support Swift?
The documentation states that Swift is fully supported and that the usage syntax is mostly the same. The library itself is written in Objective-C.
How do I lay out several views the same way in KeepLayout?
Call the attribute methods on an array of views, which creates a grouped attribute over all of them, for example `views.keepInsets.min = 10` on three views to create and configure 12 layout constraints. There are also array helpers such as `keepWidthsEqual`, `keepHorizontalOffsets:` and `keepTopAligned`.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/tricertops-keeplayout)Was this useful?