Giter Site home page Giter Site logo

compactconstraint's Introduction

CompactConstraint

A simple NSLayoutConstraint expression parser for more readable autolayout code. By Marco Arment and released under the MIT license (see LICENSE file).

Apple's visual format syntax is helpful, but it cannot express all types of autolayout constraints, and it's not ideal for simple values. Creating NSLayoutConstraints manually is more powerful and covers all possibilities, but is extremely verbose and hard to read.

CompactConstraint brings compact, readable syntax to creating NSLayoutConstraints manually. In short, rather than writing Cocoa autolayout constraints like this:

[self.view addConstraint:[NSLayoutConstraint constraintWithItem:emailLabel attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:emailField attribute:NSLayoutAttributeLeft multiplier:1.0f constant:0.0f]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:spinner attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:logInButton attribute:NSLayoutAttributeRight multiplier:1.0f constant:10.0f]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:preview attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:preview attribute:NSLayoutAttributeWidth multiplier:0.625f constant:0.0f]];

CompactConstraint lets you write them like this:

[self.view addCompactConstraint:@"emailLabel.left >= emailField.left" metrics:metrics views:views];
[self.view addCompactConstraint:@"spinner.left = logInButton.right + 10" metrics:metrics views:views];
[self.view addCompactConstraint:@"preview.height = preview.width / 1.6" metrics:metrics views:views];

Or this:

[self.view addCompactConstraints:@[
    @"emailLabel.left >= emailField.left",
    @"spinner.left = logInButton.right + 10",
    @"preview.height = preview.width / 1.6"
] metrics:metrics views:views];

Syntax

CompactConstraint syntax maps directly to the paramters passed to NSLayoutConstraint's built-in constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant: method:

leftItem.attribute [= == <= >=] rightItem.attribute [* /] multiplier [+ -] constant @ priority # identifier

leftItem and rightItem are keys from the supplied views dictionary that map to UIViews, just like with Apple's visual-format-language calls.

rightItem may be "super", which is interpreted as leftItem's superview, or "safe", which is interpreted as leftItem's superview's safeAreaLayoutGuide. If you specify @"super" or @"safe" keys in views, your supplied values will be used instead.

multiplier, constant, priority, and identifier are optional. Additionally, rightItem.attribute, multiplier, constant, and priority can all optionally be replaced by entries in the supplied metrics dictionary, mapping to NSNumbers.

In iOS 7+ anything following the # (or the format string itself if no # is present) is set as the constraint’s identifier for easier debugging. To prevent any identifier being set, end your format string with a bare #.

Valid attributes are simply the ends of the NSLayoutAttribute definitions with initial lowercase letters:

left
right
top
bottom
leading
trailing
width
height
centerX
centerY
baseline

For example, given these dictionaries as the views and metrics parameters:

NSDictionary *views = @{
    @"button" : self.button,
    @"label" : self.label,
    @"spinner" : activitySpinner,
};

NSDictionary *metrics = @{
    @"buttonHeight" : @(36),
    @"spacing" : @(15),
    @"scale" : @(1.25),
    @"highPriority", : @(UILayoutPriorityDefaultHigh),
};

These would all be valid CompactConstraint syntax:

button.centerX = super.centerX # horizontally-center button
label.width = button.width * scale + 40
spinner.left = button.right + 10 @ highPriority
button.height = buttonHeight
spinner.height = 40 @ 100

Installation

Just include the handful of files in the CompactConstraint directory in your project, and wherever you'd like to use this (or in the precompiled header): #import "CompactConstraint.h"

Is it fast?

It's fast enough for me. Try it and see if it's fast enough for you.

compactconstraint's People

Contributors

bencochran avatar claaslange avatar flainez avatar lpmi-13 avatar marcoarment avatar mbbischoff avatar sirwart avatar sjrmanning avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

compactconstraint's Issues

@"self" implicit view?

It seems that when called as a category on UIView, it would be nice to have @"self" as an implicit view (like @"super"), so that instead of this:

[_containerView addCompactConstraint:@"container.width = 320" metrics:nil views:@{@"container" : i_containerView}];

you could have:

[_containerView addCompactConstraint:@"self.width = 320" metrics:nil views:nil];

I would implement this by adding an (optional) selfView parameter to the NSLayoutConstraint category methods and using that from the UIView category methods, but it could also be done by having the UIView category "mutate" the views dictionary. The first method seems better, but it depends on how much you dislike adding either the parameter or more methods.

Constraint identifiers, a thought

iOS 8 added NSLayoutConstrain.identifier which can help making debugging constraints slightly less painful.

I was considering two additions to CompactConstraint for identifier support:

  1. Adding some sort of syntax for specifying an identifier in a compact constraint. Maybe something like item1.attribute = item2.attribute + 10 (my identifier goes here)?
  2. If no custom identifier is given, setting the entire constraint string as the identifier.

Number 2 seems pretty straightforward, but I wanted to see if there were any thoughts on syntax for specifying a custom identified before I embarked on number 1. Thoughts?

New CocoaPods release

The current version accessible through CocoaPods release is a bit old and do not support priorities. Maybe releasing a new version could be a good thing.

Warnings on casting from NSInteger to NSLayoutAttribute

With sufficient warnings enabled and NS_ENUM generating real enumerated types, there are warnings on the assignment of leftAttribute and leftAttribute from NSInteger (integerValue). Easily fixed with an explicit cast:

leftAttribute = (NSLayoutAttribute)[leftAttributeNumber integerValue];
rightAttribute = (NSLayoutAttribute)[rightAttributeNumber integerValue];

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.