{"id":15561308,"url":"https://github.com/lucasvandongen/constraint","last_synced_at":"2026-02-25T22:03:42.178Z","repository":{"id":56906543,"uuid":"139720900","full_name":"LucasVanDongen/Constraint","owner":"LucasVanDongen","description":"Constraint is a simple fluent Swift wrapper for iOS Auto Layout that has a very natural syntax","archived":false,"fork":false,"pushed_at":"2025-02-03T14:35:12.000Z","size":270,"stargazers_count":16,"open_issues_count":3,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-30T04:11:46.947Z","etag":null,"topics":["autolayout","cocoapod","cocoapods","ios","swift","swift4","swift5"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/LucasVanDongen.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-07-04T12:44:27.000Z","updated_at":"2025-03-29T20:36:34.000Z","dependencies_parsed_at":"2022-08-21T03:20:46.171Z","dependency_job_id":null,"html_url":"https://github.com/LucasVanDongen/Constraint","commit_stats":null,"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LucasVanDongen%2FConstraint","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LucasVanDongen%2FConstraint/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LucasVanDongen%2FConstraint/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LucasVanDongen%2FConstraint/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/LucasVanDongen","download_url":"https://codeload.github.com/LucasVanDongen/Constraint/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250528680,"owners_count":21445511,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["autolayout","cocoapod","cocoapods","ios","swift","swift4","swift5"],"created_at":"2024-10-02T16:07:22.418Z","updated_at":"2026-02-25T22:03:42.143Z","avatar_url":"https://github.com/LucasVanDongen.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Constraint\nConstraint is a simple wrapper for iOS Auto Layout that has a very natural syntax\n\n[![CI Status](https://img.shields.io/travis/lucasvandongen/Constraint.svg?style=flat)](https://travis-ci.org/LucasVanDongen/Constraint)\n[![Version](https://img.shields.io/cocoapods/v/Constraint.svg?style=flat)](https://cocoapods.org/pods/Constraint)\n[![License](https://img.shields.io/cocoapods/l/Constraint.svg?style=flat)](https://cocoapods.org/pods/Constraint)\n[![Platform](https://img.shields.io/cocoapods/p/Constraint.svg?style=flat)](https://cocoapods.org/pods/Constraint)\n\n## Usage\n### On a UIView\nUsually you will use the `Constraint` library on an instance of the (descendant class of) `UIView` you want to constrain. Every call returns the `UIView` again so it's very easy to chain all of your layouts like this:\n\n```swift    \nicon\n    .attach(top: 20,\n            leading: 10,\n            bottom: 0,\n            trailing: 10)\n    .size(width: 24, height: 24)\n```\n\nAlso there's the possibility to add various modifiers to offset constraints:\n\n```swift\nimage.attach(top: 0.orMore, bottom: 12.defaultLowPrioritized)\n// These are also chainable\nlabel.attach(bottom: 0.orMore.prioritized(to: UILayoutPriority(800))\n```\nIf you want to save a certain `Offset` for reuse you can do that like this:\n\n```swift\nlet offset = 0.orMore.defaultLowPrioritized.respectingLayoutGuides\n```\nIt's possible to respect any layout guide (like iPhone X's Safe Area) by using `respectingLayoutGuide` / `layoutGuideRespecting`\n### On an array of UIViews\nIt's also possible to work with arrays of views. For example it's now possible to space an array in a certain direction or to attach them all to their parentviews. The most used function is simply to add them as subviews:\n\n`[view1, view2, view3].addedAsSubviews(to: superView).attach()`\n\nAs you see this method is also fluent.\n\n### As a generator for constraints\nSometimes you need to store the constraints that are generated. In this case you need to call the static methods on the `Constraint` class directly as follows:\n\n```swift\nprivate var messageHeight: NSLayoutContraint?\n// ...\nmessageHeight = Constraint.height(50, for: message).activated\n```\n    \nIn this case you will have to add the constraint manually to the view. It's the maximum amount of flexibility but a bit more work.\n## UIView API\nThese are all the publicly exposed extensions to `UIView`. They are based upon the options you see in `Interface Builder`. Here's a short overview to see how they are related:\n\n![Align Screen](https://github.com/LucasVanDongen/Constraint/raw/master/Images/align.png)\n\n * The `align()` functions map to the first 7 options that are relations between two equal views\n * The `center()` functions are used for the last two options of the Align screen, where a `subview` is centered in it's `superview`\n\n![Size Constraints](https://github.com/LucasVanDongen/Constraint/raw/master/Images/size_constraints.png)\n\n * `Spacing to nearest neighbor` is covered by all of the `attach()` functions\n * `Width`, `Height`, `Equal Widths` and `Equal Heights` are covered by `width()`, `height()` and `size()`\n * `Aspect Ratio` is handled by the `ratio()` function\n * `Align` is an alias for the Edges in the Align screen and therefore is covered by `align`\n\n----------------------\n\n### `attach`\nThis method is used to space the view related to is `superview`. You can define all sides at once, every side separately and leave some sides out. It takes `Offsetable` as it's parameter which means you can either use a primitive like `Int` or `CGFloat` or you can send an `Offset` directly. \n#### Attaching all sides at once\nThis is the most basic way to use `attach`. You can define an `offset` or accept the default of `0`:\n\n```swift\nview.attach() \nview.attach(offset: 12)\n```\n#### Attach only some sides\nThis version lets you specify which sides are going to be attached. You can define an `offset` or accept the default of `0`:\n\n```swift\nview.attach(sides: [.top, .leading, .trailing], 12)\n```\n#### Attach with different values per side\nThis is the most flexible way to use this API. Every side can have it's own separate definition which is `Offsetable` so can be mutated further when needed.\n\n```swift\nview.attach(top: 0, trailing: 12) // Does not apply the bottom and leading constraints\nview.attach(top: 0.orMore) // It's possible to use it with primitives and still modify the priority or relation type\nview.attach(leading: 12.orLess.defaultLowPriority) // These can also be chained\nview.attach(bottom: Offset(0, .orMore, respectingLayoutGuide: true, priority: .defaultLow)) // Means the same as view.attach(bottom: 0.orMore.layoutGuideRespecting.defaultLowPriority)\n```\n`respectingLayoutGuide` / `layoutGuideRespecting` means it respects the layout guides, like in the root view of a `ViewController` where you expect it to respect the Safe Area sometimes. \n\nThe default is to *not* respect the layout guides.\n\n### `center`\nCenter lets you center the view inside another view, where it defaults to the `superview`. It's also possible to specify another view that needs to be part of the same view tree\n\n```swift\nview.center(axis: .both) // Centers the view on both the X and Y axis of it's superview\nview.center(axis: .x, adjusted: 10, priority: .defaultLow) // Wants to center it's X to it's superview, then adjusts it +10 pixels and applies a low priority to it\n```\n### `align`\nAlign is used where you want to align two views that are not in a parent / child relationship.\n#### Centering views with eachother\nCenters can be aligned much like the `center()` API does for parent / child views:\n\n```swift\nview.align(axis: .x, to: anotherView, adjustment: 10) // Wants to center it's X to anotherView, then adjusts it +10 pixels\n```\n#### Aligning sides of views\nIt also allows you to align a side instead of the middle:\n\n```swift\nview.align(.leading, 12, otherView) // Aligns it's leading side to the leading side of otherView + 12 pixels\n```\n\nIf you want to align multiple sides (much like `attach` does) you can do this too:\n\n```swift\nview.align([.top, .leading, .bottom], 0, to: otherView)\n```\n\n### `space`\nSpace the view to another view in any direction.\n\n```swift\nregisterButton\n    .space(20, .above, reconfirmButton)\n    .space(8, .below, usernameLabel, .orMore, priority: .defaultLow)\n```\n### `width`, `height` and `size`\nThese functions are used to set the size of a UIView. You can set the width and height also related to the width or height of another view.\n#### Setting width, height and size as a constant\n\n```swift\notherView\n    .size(width: 100, .orMore, height: 50)\nview\n    .width(200)\n    .height(100)\n```\n\n`size()` also accepts a `CGRect` as a parameter which can be handy if you for example want to copy `frame.size`\n\n```swift\nview.size(superview.frame.size)\n```\n\n#### Setting width or height related to another view\nYou can also make it relative to another view:\n\n```Swift\nview.height(relatedTo: superview, adjusted: 10)\n```\n### `ratio`\nRatio sets the ratio between the width and the height of view.\n\n```swift\nview.ratio(of: 2) // Makes the width twice as much as the height\nview.ratio(of: 3, to: 2) // Makes the width height have a ratio of 3:2\n```\nAlternatively, you can also call it with a `CGRect`. This is very handy if you want your `UIImageView` always have the same ratio as your `UIImage`:\n\n```swift\nview.ratio(avatarImage.size)\n```\n\n## UIViewController API\nWith vanilla `UIKit` nesting ViewControllers requires an even bigger amount of effort, taking at least three lines of code before even getting to the point where you can start to set up your constraints:\n\n```swift\naddChild(viewController)\nparentView.addSubview(viewController.view)\nviewController.didMove(toParent: self)\n```\n\nWithout `Constraint` you would add at least another five lines of NSLayoutConstraint code to just align the edges to the parent view:\n\n```swift\nviewController.view.translatesAutoresizingMaskIntoConstraints = false\n\nviewController.view.topAnchor.constraint(equalTo: view.topAnchor).isActive = true\nviewController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true\nviewController.view.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true\nviewController.view.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true\n```\n\nWhen decomposing your Views into smaller Subviews is so hard, it's not very unexpected that many UIKit developers tend to put so much stuff into one ViewController. It's very disencouraging to do the right thing. \n\n### `embed`\nThe `embed` function takes away a lot of the boiler plate code. Embedding ViewControllers now looks like this:\n\n```\nembed(viewController: childViewController) // Was: 3 lines of code to add the child\n    .attach()                              // Was: 5 lines of code to align the child\n```\n\nWhen it gets that easy to add child ViewControllers, you will use it way more often.\n\n## Known issues and TODO's\nThis is the `0.9` release of this library but it already has been used in a few projects internally and all of the major kinks have been worked out. The last major hurdle for full functionality is being able to capture all created constraints, so they can be turned on and off programmatically.\n\n## Example\n\nTo run the example project, clone the repo, and run `pod install` from the Example directory first.\n\n## Requirements\n* Swift 4 or higher\n* iOS (or related platforms)\n\n## Installation\nConstraint is available through [Swift Package](https://swift.org/package-manager/). [CocoaPods](https://cocoapods.org) support still exists, but will be less frequently updated.\n\n### SPM\n* Open the project you want to add the dependency to\n* Go to `File` \u003e `Swift Packages` \u003e `Add Package Dependency`\n* Enter `https://github.com/LucasVanDongen/Constraint` in the `Enter package repository URL` textfield\n* Click `Next`\n* Change the version you want or leave it as is\n* Click `Next`\n* Once it's done installing tap `Finish`\n\n### Cocoapods\nTo install\nit, simply add the following line to your Podfile:\n\n```ruby\npod 'Constraint'\n``` \n\n## Author\n\nBuilt for [Blue Rhizome](https://bluerhizome.com) by Lucas van Dongen, \u003cme@lucasvandongen.dev\u003e @ [`lucasvandongen.dev`](https://lucasvandongen.dev) \n\n## License\n\nConstraint is available under the MIT license. See the LICENSE file for more info.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flucasvandongen%2Fconstraint","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flucasvandongen%2Fconstraint","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flucasvandongen%2Fconstraint/lists"}