Write AutoLayout constraints as simple equations.
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
SimpleConstraintProject.xcodeproj
SimpleConstraintProject
SimpleConstraintTests
lib-prefixed
lib
LICENSE
README.md

README.md

SimpleConstraint

SimpleConstraint is a library for defining AutoLayout constraints in code using equations.

Basic Example

AddConstraints({
	thumbnail.top = self.top + 20;
	thumbnail.left = self.left + 10;
	thumbnail.right = self.right - 10;
	text.top = thumbnail.bottom + 5;
	text.centerX = thumbnail.centerX;
});

Is the equivalent of:

NSArray *constraints = @[
		[NSLayoutConstraint constraintWithItem:thumbnail 
									 attribute:NSLayoutAttributeTop 
									 relatedBy:NSLayoutRelationEqual 
										toItem:self 
									 attribute:NSLayoutAttributeTop 
									multiplier:1 
									  constant:20],
		[NSLayoutConstraint constraintWithItem:thumbnail 
									 attribute:NSLayoutAttributeLeft 
									 relatedBy:NSLayoutRelationEqual 
										toItem:self 
									 attribute:NSLayoutAttributeLeft 
									multiplier:1 
									  constant:10],
		[NSLayoutConstraint constraintWithItem:thumbnail 
									 attribute:NSLayoutAttributeRight 
									 relatedBy:NSLayoutRelationEqual
										toItem:self
									 attribute:NSLayoutAttributeRight 
									multiplier:1
									  constant:-10],
		[NSLayoutConstraint constraintWithItem:text
									 attribute:NSLayoutAttributeTop
									 relatedBy:NSLayoutRelationEqual
										toItem:thumbnail
									 attribute:NSLayoutAttributeBottom 
									multiplier:1 
									  constant:5],
		[NSLayoutConstraint constraintWithItem:text
									 attribute:NSLayoutAttributeCenterX 
									 relatedBy:NSLayoutRelationEqual
										toItem:thumbnail
									 attribute:NSLayoutAttributeCenterX 
									multiplier:1 
									  constant:0]
];
thumbnail.translatesAutoresizingMaskIntoConstraints = NO;
text.translatesAutoresizingMaskIntoConstraints = NO;
[self addConstraints:constraints];

The syntax emphasizes readability, and allows the use of both view and primitive variables without requiring them to be put into dictionaries. It also gives the benefits of code completion and syntax highlighting.

How to use

All equations must be written in the form:

targetView.property = referenceView.property * multiplier + constant +/- flex();

Rearranging an equation (for example so the constant is the first thing on the right side) is fine, but it must be able to simplify down to this basic form. In other words, you must have:

  • A target view and property.
  • A reference view and property (if omitted, will be nil and NSLayoutAttributeNotAnAttribute).
  • A multiplier (if omitted, will be 1).
  • A constant (if omitted, will be 0).
  • An optional flex() value can be added or subtracted. Using + flex() will specify that the target property can be greater than or equal to the value on the right. Using - flex() specifies less than or equal.

Chaining multiple equations, such as view1.left = view2.left = view3.left; does not work, unless the final value is only a constant, with no reference property. For consistency, it should probably be avoided even then.

The following view properties are available, which correspond to the various NSLayoutAttributes:

  • left
  • right
  • top
  • bottom
  • centerX
  • centerY
  • width
  • height
  • leading
  • trailing
  • baseline

These view properties are meaningless outside of either AddConstraint() or AddConstraints(), and should not be set or accessed.

A single constraint should be wrapped with AddConstraint():

NSLayoutConstraint *constraint = AddConstraint(label.width = thumbnail.width * 1.1);

And multiple constraints should be wrapped in AddConstraints():

NSArray *constraints = AddConstraints({
	thumbnail.width = 50;
	thumbnail.height = 40;
});

Constraints are automatically added to the nearest common ancestor of both the target view and the reference view. The target view's translatesAutoresizingMaskIntoConstraints is automatically set to NO.

Prefixing

There are two versions of the library, one (in the "lib-prefixed" folder) with prefixed property and macro names to avoid collisions:

SCAddConstraint(view.sc_left = view2.sc_left);

And one without (in the "lib" folder):

AddConstraint(view.left = view2.left);

I generally prefer the prettier, more readable, non-prefixed properties, but the prefixed version should be used if there are any naming conflicts, or if you just want to play it safe.

License

Licensed under the MIT license.