{"id":16064438,"url":"https://github.com/nakiostudio/easypeasy","last_synced_at":"2025-10-24T23:15:29.417Z","repository":{"id":6135628,"uuid":"54736580","full_name":"nakiostudio/EasyPeasy","owner":"nakiostudio","description":"Auto Layout made easy ","archived":false,"fork":false,"pushed_at":"2022-03-17T09:33:24.000Z","size":9936,"stargazers_count":1939,"open_issues_count":17,"forks_count":117,"subscribers_count":38,"default_branch":"master","last_synced_at":"2025-10-19T21:50:03.862Z","etag":null,"topics":["auto","auto-layout","constraints","easypeasy","ios","layout","swift"],"latest_commit_sha":null,"homepage":"easy-peasy.io","language":"Swift","has_issues":false,"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/nakiostudio.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"ko_fi":"nakiostudio"}},"created_at":"2016-03-25T17:51:31.000Z","updated_at":"2025-10-08T05:49:37.000Z","dependencies_parsed_at":"2022-08-06T19:15:18.191Z","dependency_job_id":null,"html_url":"https://github.com/nakiostudio/EasyPeasy","commit_stats":null,"previous_names":[],"tags_count":26,"template":false,"template_full_name":null,"purl":"pkg:github/nakiostudio/EasyPeasy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nakiostudio%2FEasyPeasy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nakiostudio%2FEasyPeasy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nakiostudio%2FEasyPeasy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nakiostudio%2FEasyPeasy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nakiostudio","download_url":"https://codeload.github.com/nakiostudio/EasyPeasy/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nakiostudio%2FEasyPeasy/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":280879133,"owners_count":26406802,"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","status":"online","status_checked_at":"2025-10-24T02:00:06.418Z","response_time":73,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["auto","auto-layout","constraints","easypeasy","ios","layout","swift"],"created_at":"2024-10-09T05:07:49.314Z","updated_at":"2025-10-24T23:15:29.400Z","avatar_url":"https://github.com/nakiostudio.png","language":"Swift","funding_links":["https://ko-fi.com/nakiostudio"],"categories":[],"sub_categories":[],"readme":"\u003ch3 align=\"center\"\u003e\n\u003cimg src=\"/README/logo.png\" alt=\"EasyPeasy Logo\" /\u003e\n\u003c/h3\u003e\n\n[![CI Status](http://img.shields.io/travis/nakiostudio/EasyPeasy.svg?style=flat)](https://travis-ci.org/nakiostudio/EasyPeasy)\n[![Version](https://img.shields.io/cocoapods/v/EasyPeasy.svg?style=flat)](http://cocoapods.org/pods/EasyPeasy)\n[![Carthage compatible](https://img.shields.io/badge/carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)\n[![Coverage](https://img.shields.io/badge/coverage-100%25-brightgreen.svg)](https://travis-ci.org/nakiostudio/EasyPeasy)\n\n**EasyPeasy** is a Swift framework that lets you create *Auto Layout* constraints\nprogrammatically without headaches and never ending boilerplate code. Besides the\nbasics, **EasyPeasy** resolves most of the constraint conflicts for you and also\ncan attach to a constraint conditional closures that are evaluated before applying\na constraint, this way you can install an *Auto Layout* constraint depending on\nplatform, size classes, orientation... or the state of your controller, easy peasy!\n\nIn this quick tour through **EasyPeasy** we assume that you already know the\nadvantages and disadvantages of the different *Auto Layout* APIs and therefore you\nwon't see here a comparison of the code side by side, just read and decide\nwhether **EasyPeasy** is for you or not.\n\n### A touch of EasyPeasy\nThe example below is quite simple but shows how effortless its implementation\nresult using **EasyPeasy**.\n\u003ch3 align=\"center\"\u003e\n\u003cbr\u003e\n\u003cimg width=\"80%\" src=\"/README/first_touch.png\" alt=\"First touch\" /\u003e\n\u003c/h3\u003e\n\n### Features\n\n* Compatible with iOS, tvOS and OS X.\n* Lightweight and easy to use domain specific language.\n* Resolution of *Auto Layout* conflicts.\n* Fast and *hassle-free* update of constraints.\n* Conditional application of constraints.\n* `UILayoutGuide` and `NSLayoutGuide` support.\n\n### Guides\n\n* [Mastering Auto Layout with EasyPeasy I: Introduction](https://medium.com/@yaid/mastering-auto-layout-with-easypeasy-i-introduction-341f12230074)\n* [Mastering Auto Layout with EasyPeasy II: Basics](https://medium.com/@yaid/mastering-auto-layout-with-easypeasy-ii-basics-3057e1db817)\n* [Mastering Auto Layout with EasyPeasy III: Relationships](https://medium.com/@yaid/mastering-auto-layout-with-easypeasy-iii-relationships-91fc140e4755)\n* Mastering Auto Layout with EasyPeasy IV: Priorities *(coming soon...)*\n* Mastering Auto Layout with EasyPeasy V: Layout Guides *(coming soon...)*\n* Mastering Auto Layout with EasyPeasy VI: Advanced *(coming soon...)*\n\n## Table of contents\n\n* [Installation](#installation)\n* [Usage](#usage)\n  * [Constants](#constants)\n  * [Attributes](#attributes)\n    * [DimensionAttributes](#dimensionattributes)\n    * [PositionAttributes](#positionattributes)\n    * [CompoundAttributes](#compoundattributes)\n  * [Priorities](#priorities)\n  * [Conditions](#conditions)\n    * [ContextualConditions](#contextualconditions)\n  * [UILayoutGuides](#uilayoutguides)\n  * [Lastly](#lastly)\n    * [Updating constraints](#updating-constraints)\n    * [Clearing constraints](#clearing-constraints)\n    * [Animating constraints](#animating-constraints)\n* [Example projects](#example-projects)\n* [EasyPeasy playground](#easypeasy-playground)\n* [Autogenerated documentation](#autogenerated-documentation)\n\n## Installation\n\n### Swift compatibility\n* To work with Swift 2.2 use EasyPeasy `v.1.2.1` or earlier versions of the library.\n* To work with Swift 2.3 use EasyPeasy `v.1.3.1`.\n* To work with Swift 3 use EasyPeasy `v.1.4.2`.\n* To work with Swift 4 use EasyPeasy `v.1.8.0`.\n* To work with Swift 5 use EasyPeasy `v.1.9.0` and above.\n(thanks [Bas van Kuijck](https://github.com/basvankuijck)).\n\n### Cocoapods\nEasyPeasy is available through [CocoaPods](http://cocoapods.org). To install\nit, simply add the following line to your Podfile:\n\n```ruby\npod \"EasyPeasy\"\n```\n\n### Carthage\nEasyPeasy is [Carthage](https://github.com/Carthage/Carthage) compatible.\nTo add **EasyPeasy** as a dependency to your project, just add the following line\nto your Cartfile:\n\n```ruby\ngithub \"nakiostudio/EasyPeasy\"\n```\n\nAnd run ` carthage update ` as usual.\n\n### Compatibility\n**EasyPeasy** is compatible with iOS (8 and above), tvOS (9 and above) and OS X\n(10.10 and above).\nThe framework has been tested with Xcode 7 and Swift 2.0, however don't hesitate\nto report any issues you may find with different versions.\n\n## Usage\n\n**EasyPeasy** is a set of position and dimension attributes that you can apply\nto your views. You can manage these from the  `easy` property available within all\nthe UI classes that work with Auto Layout (view subclasses, layout guides, etc).\n\nFor instance, to set a width of 200px to a view you would create\nan attribute of class `Width` with a constant value of `200`, then the attribute\nis applied to the view by using the `easy.layout(_:)` method.\n\n```swift\nmyView.easy.layout(Width(200))\n```\n\nBecause our view without height is nothing we can apply multiple attributes at\nonce as follows:\n\n```swift\nmyView.easy.layout(\n  Width(200),\n  Height(120)\n)\n```\n\nIn the previous example, two attributes have been applied and therefore two constraints\ncreated and added: a width constraint with `constant = 200` and a height constraint\nwith `constant = 120`.\n\n### Constants\nWithout really knowing it, we have just created an **EasyPeasy** `Constant` struct\ncontaining the constant, multipler and the relation of a `NSLayoutConstraint`.\n\n#### Relations\n**EasyPeasy** provides an easy way of creating constants with different\n`NSLayoutRelations`:\n\n* `.Equal`: it is created like in our previous example `Width(200)`.\n* `.GreaterThanOrEqual`: it is created as easy as this `Width(\u003e=200)` and it means\nthat our view has a width greater than or equal to 200px.\n* `.LessThanOrEqual`: it is created as follows `Width(\u003c=200)`.\n\n#### Multipliers\nThere is a custom operator that eases the creation of a `NSLayoutConstraint` multiplier.\nYou can use it like this `Width(*2)` and means that the width of our view is two times\n*something*, we will mention later how to establish the relationship with that *something*.\n\nIn addition, you can combine `multipliers` with `Equal`, `.GreaterThanOrEqual` and\n`LessThanOrEqual` relations. i.e. `Width(\u003e=10.0*0.5)` creates a `NSLayoutConstraint`\nwith `value = 10.0`, `relation = .GreaterThanOrEqual` and `multiplier = 0.5`, whereas\n`Width(==10.0*0.5)` creates a `NSLayoutConstraint` with `value = 10.0`,\n`relation = .Equal` and `multiplier = 0.5`.\n\n### Attributes\n**EasyPeasy** provides as many `Attribute` classes as attributes `NSLayoutConstraint`\nhave, plus something that we have called `CompoundAttributes` (we will explain these\nattributes later).\n\n#### DimensionAttributes\nThere are just two dimension attributes `Width` and `Height`. You can create an\n*Auto Layout* relationship between your view `DimensionAttribute` and another view\nby using the method `func like(view: UIView) -\u003e Self`. Example:\n\n```swift\ncontentLabel.easy.layout(Width().like(headerView))\n```\n\nThat line of code will create a constraint that sets a width for `contentLabel`\nequal to the `headerView` width.\n\n#### PositionAttributes\nThe table below shows the different position attributes available. Because they\nbehave like the `NSLayoutConstraint` attributes, you can find a complete\ndescription of them in the [Apple docs](https://developer.apple.com/library/ios/documentation/AppKit/Reference/NSLayoutConstraint_Class/#//apple_ref/c/tdef/NSLayoutRelation).\n\nAttribute | Attribute | Attribute | Attribute\n--- | --- | --- | ---\nLeft | Right | Top | Bottom\nLeading | Trailing | CenterX | CenterY\nLeftMargin | RightMargin | TopMargin | BottomMargin\nLeadingMargin | TrailingMargin | CenterXWithinMargins | CenterYWithinMargins\nFirstBaseline | LastBaseline | -- | --\n\nAs well as the **DimensionAttributes** have the `like:` method to establish\n*Auto Layout* relationships, you can use a similar method to do the same with\n**PositionAttributes**. This method is:\n\n```swift\nfunc to(view: UIView, _ attribute: ReferenceAttribute? = nil) -\u003e Self\n```\n\nThe example below positions `contentLabel` 10px under `headerView` with the same\nleft margin as `headerView`.\n\n```swift\ncontentLabel.easy.layout(\n  Top(10).to(headerView),\n  Left().to(headerView, .Left)\n)\n```\n\n#### CompoundAttributes\nThese attributes are the ones that create multiple `DimensionAttributes` or\n`PositionAttributes` under the hood. For example, the `Size` attribute will create\na `Width` and a `Height` attributes with their width and height\n`NSLayoutConstraints` respectively.\n\nThese are the `CompoundAttributes` available:\n\n* `Size`: As mentioned before this attribute will apply a `Width` and a `Height`\nattribute to the view. It can be initialized in many ways and depending on that\nthe result may change. These are some examples:\n\n```swift\n// Apply width = 0 and height = 0 constraints\nview.easy.layout(Size())\n// Apply width = referenceView.width and height = referenceView.height constraints\nview.easy.layout(Size().like(referenceView))\n// Apply width = 100 and height = 100 constraints\nview.easy.layout(Size(100))\n// Apply width = 200 and height = 100 constraints\nview.easy.layout(Size(CGSize(width: 200, height: 100)))\n```\n\n* `Edges`: This attribute creates `Left`, `Right`, `Top` and `Bottom` attributes\nat once. Examples:\n\n```swift\n// Apply left = 0, right = 0, top = 0 and bottom = 0 constraints to its superview\nview.easy.layout(Edges())\n// Apply left = 10, right = 10, top = 10 and bottom = 10 constraints to its superview\nview.easy.layout(Edges(10))\n// Apply left = 10, right = 10, top = 5 and bottom = 5 constraints to its superview\nview.easy.layout(Edges(UIEdgeInsets(top: 5, left: 10, bottom: 5, right: 10)))\n```\n\n* `Center`: It creates `CenterX` and `CenterY` attributes. Examples:\n\n```swift\n// Apply centerX = 0 and centerY = 0 constraints to its superview\nview.easy.layout(Center())\n// Apply centerX = 10 and centerY = 10 constraints to its superview\nview.easy.layout(Center(10))\n// Apply centerX = 0 and centerY = 50 constraints to its superview\nview.easy.layout(Center(CGPoint(x: 0, y: 50)))\n```\n\n* `Margins`: This attribute creates `LeftMargin`, `RightMargin`, `TopMargin` and\n`BottomMargin` attributes at once. Examples:\n\n```swift\n// Apply leftMargin = 0, rightMargin = 0, topMargin = 0 and bottomMargin = 0 constraints to its superview\nview.easy.layout(Margins())\n// Apply leftMargin = 10, rightMargin = 10, topMargin = 10 and bottomMargin = 10 constraints to its superview\nview.easy.layout(Margins(10))\n// Apply leftMargin = 10, rightMargin = 10, topMargin = 5 and bottomMargin = 5 constraints to its superview\nview.easy.layout(Margins(UIEdgeInsets(top: 5, left: 10, bottom: 5, right: 10)))\n```\n\n* `CenterWithinMargins`: It creates `CenterXWithinMargins` and `CenterYWithinMargins`\nattributes. Examples:\n\n```swift\n// Apply centerXWithinMargins = 0 and centerYWithinMargins = 0 constraints to its superview\nview.easy.layout(CenterWithinMargins())\n// Apply centerXWithinMargins = 10 and centerYWithinMargins = 10 constraints to its superview\nview.easy.layout(CenterWithinMargins(10))\n// Apply centerXWithinMargins = 0 and centerYWithinMargins = 50 constraints to its superview\nview.easy.layout(CenterWithinMargins(CGPoint(x: 0, y: 50)))\n```\n\n### Priorities\n\nThe `Priority` enum does the same function as `UILayoutPriority` and it's shaped\nby five cases:\n* `low`: it creates an *Auto Layout* priority with `Float` value `1`.\n\n* `medium`: it creates an *Auto Layout* priority with `Float` value `500`.\n\n* `high`: it creates an *Auto Layout* priority with `Float` value `750`.\n\n* `required`: it creates an *Auto Layout* priority with `Float` value `1000`.\n\n* `custom`: it specifies the *Auto Layout* priority defined by the\ndeveloper in the case associated value `value`. Example: `.custom(value: 650.0)`.\n\nIn order to apply any of these priorities to an `Attribute`, the method\n`.with(priority: Priority)` must be used. The following example gives an\n`UILayoutPriority` of `500` to the `Top` `Attribute` applied to `view`:\n\n```swift\nview.easy.layout(Top(\u003e=50).with(.medium))\n```\n\nYou can also apply a `Priority` to an array of `Attributes` (this operation will\noverride the priorities previously applied to an `Attribute`).\n\n```swift\nview.easy.layout([\n  Width(200),\n  Height(200)\n].with(.medium))\n```\n\n### Conditions\nOne of the peculiarities of **EasyPeasy** is the usage of `Conditions` or closures\nthat evaluate whether a constraint should be applied or not to the view.\n\nThe method `when(condition: Condition)` sets the `Condition` closure to an `Attribute`.\n\nThere is plenty of use cases, the example below shows how to apply different\nconstraints depending on a custom variable:\n\n```swift\nvar isCenterAligned = true\n...\nview.easy.layout(\n  Top(10),\n  Bottom(10),\n  Width(250),\n  Left(10).when { !isCenterAligned },\n  CenterX(0).when { isCenterAligned }\n)\n```\n\n#### Condition re-evaluation\nThese `Condition` closures can be re-evaluated during the lifecycle of a view,\nto do so you just need to call the convenience method `easy.reload()`.\n\n```swift\nview.easy.reload()\n```\n\nBare in mind that these `Condition` closures are stored in properties therefore\nyou need to capture those variables you access within the closure. For example:\n\n```swift\ndescriptionLabel.easy.layout(\n  Height(100).when { [weak self] in\n    return self?.expandDescriptionLabel ?? false\n  }\n)\n```\n\nYou can also apply a `Condition` to an array of `Attributes` (this operation will\noverride the `Conditions` previously applied to an `Attribute`).\n\n```swift\nview.easy.layout([\n  Width(200),\n  Height(240)\n].when { isFirstItem })\n\nview.easy.layout([\n  Width(120),\n  Height(140)\n].when { !isFirstItem })\n```\n\n#### ContextualConditions\nThis iOS only feature is a variant of the `Condition` closures that receive no\nparameters and return a boolean value. Instead, a `Context` struct is passed\nas parameter providing some extra information based on the `UITraitCollection`\nof the `UIView` the `Attributes` are going to be applied to.\n\nThe properties available on this `Context` struct are:\n\n* `isPad`: true if the current device is iPad.\n* `isPhone`: true if the current device is iPhone.\n* `isHorizontalVerticalCompact`: true if both horizontal and vertical size\nclasses are `.Compact`.\n* `isHorizontalCompact`: true if the horizontal size class is `.Compact`.\n* `isVerticalCompact`: true if the vertical size class is `.Compact`.\n* `isHorizontalVerticalRegular`: true if both horizontal and vertical size\nclasses are `.Regular`.\n* `isHorizontalRegular`: true if the horizontal size class is `.Regular`.\n* `isVerticalRegular`: true if the vertical size class is `.Regular`.\n\nThis is an example of `ContextualConditions` applied to an array of\n`Attributes`:\n\n```swift\nview.easy.layout([\n  Size(250),\n  Center(0)\n].when { $0.isHorizontalRegular })\n\nview.easy.layout([\n  Top(0),\n  Left(0),\n  Right(0),\n  Height(250)\n].when { $0.isHorizontalCompact })\n```\n\n##### ContextualCondition re-evaluation\nAs we have seen before, you can re-evaluate a `Condition` closure by calling\nthe `easy.reload()` convenience method. This also applies to\n`ContextualConditions`, therefore if you want your constraints to be updated\nupon a change on your view `UITraitCollection` then you need to call the\n`easy.reload()` method within `traitCollectionDidChange(_:)`.\n\nAlternatively, **EasyPeasy** can do this step for you automatically. This is\ndisabled by default as it requires method swizzling; to enable it simply\n**compile the framework** adding the compiler flags `-D EASY_RELOAD`.\n\n### UILayoutGuides\nSince the version *v.0.2.3* (and for iOS 9 projects and above) **EasyPeasy**\nintegrates `UILayoutGuides` support.\n\n#### Applying constraints\nApplying a constraint to an `UILayoutGuide` is as easy as we have discussed in the\nprevious sections, just apply the **EasyPeasy** attributes you want using the\n`easy.layout(_:)` method.\n\n```swift\nfunc viewDidLoad() {\n  super.viewDidLoad()\n\n  let layoutGuide = UILayoutGuide()\n  self.view.addLayoutGuide(layoutGuide)\n\n  layoutGuide.easy.layout(\n    Top(10),\n    Left(10),\n    Right(10),\n    Height(100).when { Device() == .iPad },\n    Height(60).when { Device() == .iPhone }\n  )\n}\n```\n\nAs you can see, all the different attributes and goodies **EasyPeasy** provides for\n`UIViews` are also applicable to `UILayoutGuides`.\n\n#### Connecting UILayoutGuides and UIViews\nAs mentioned in the [Attributes](#attributes) section you can create constraint\nrelationships between an `UIView` attribute and other `UIViews` attributes using\nthe methods `to(_:_)` and `like(_:_)`. Now you can take advantage of those methods\nto create a relationship between your `UIView` attributes and an `UILayoutGuide`.\n\n```swift\nlet layoutGuide = UILayoutGuide()\nlet separatorView: UIView\nlet label: UILabel\n\nfunc setupLabel() {\n  self.label.easy.layout(\n    Top(10).to(self.layoutGuide),\n    CenterX(0),\n    Size(60)\n  )\n\n  self.separatorView.easy.layout(\n    Width(0).like(self.layoutGuide),\n    Height(2),\n    Top(10).to(self.label),\n    CenterX(0).to(self.label)\n  )\n}\n```\n\n### Lastly\nFinally but not less important in this section we will explain how to interact\nwith `Attributes` once they have been applied to an `UIView` using the\n`easy.layout(_:)` method.\n\n#### Updating constraints\nWe briefly mentioned in the introductory section that **EasyPeasy** solves most\nof the constraint conflicts and it's true. Usually, in order to update a constraint\nor the constant of a constraint you have to keep a reference to your\n`NSLayoutConstraint` and update the constant when needed. With **EasyPeasy** you\njust need to apply another `Attribute` to your `UIView` of the same or different\ntype. In the example below we have two methods, the one in which we setup our\nconstraints `viewDidLoad()` and a method in which we want to update the `Top`\nattribute of our `headerView`.\n\n```swift\nfunc viewDidLoad() {\n  super.viewDidLoad()\n\n  headerView.easy.layout(\n    Top(0),\n    Left(0),\n    Right(0),\n    Height(60)\n  )\n}\n\nfunc didTapButton(sender: UIButton?) {\n  headerView.easy.layout(Top(100))\n}\n```\n\nThat's it! we have updated our `Top` constraint without caring about keeping\nreferences or installing/uninstalling new constraints.\n\nHowever, there is some cases in which **EasyPeasy** cannot prevent a conflict (at\nleast for now). This is when multiple constraints cannot be satisfied, i.e. existing\na `Left` and `Right` constraints it's also applied a `Width` constraint (all of them\nwith the same priority). But **EasyPeasy** is smart enough to prevent conflicts,\ni.e. when replacing a `Left` and `Right` attributes with a `CenterX` attribute.\n\n#### Clearing constraints\n**EasyPeasy** provides a method extending `UIView` that clears all the constraints\ninstalled in an `UIView` by the framework. This method is `func easy.clear()`.\n\n```swift\nview.easy.clear()\n```\n\n#### Animating constraints\nAnimating constraints with **EasyPeasy** is very straightforward, just apply one\nor more `Attributes` to your view within an animation block and you are ready to\ngo, without worrying about constraint conflicts. Example:\n\n```swift\nUIView.animateWithDuration(0.3) {\n  view.easy.layout(Top(10))\n  view.layoutIfNeeded()\n}\n```\n\n## Example projects\n\nDon't forget to clone the repository and run the iOS and OS X example projects\nto see **EasyPeasy** in action.\n\n\u003ch3 align=\"center\"\u003e\n\u003ctable width=\"50%\"\u003e\n  \u003ctr\u003e\n  \u003ctd width=\"50%\"\u003e\n    \u003cimg src=\"/README/demo_ios.gif\" alt=\"Demo iOS\" /\u003e\n  \u003c/td\u003e\n  \u003ctd width=\"50%\"\u003e\n    \u003cimg src=\"/README/demo_macos.gif\" alt=\"Demo macOS\" /\u003e\n  \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\u003c/h3\u003e\n\n*Note:* the messages in the demo app aren't real and the appearance of\nthose *Twitter* accounts no more than a tribute to some kickass developers :)\n\n## EasyPeasy playground\n\nAlternatively, you can play with **EasyPeasy** cloning the *Playground* project\navailable [here](https://github.com/nakiostudio/EasyPeasy-Playground).\n\n\u003ch3 align=\"center\"\u003e\n\u003cimg src=\"/README/playground.gif\" alt=\"Playground\" /\u003e\n\u003c/h3\u003e\n\n## Autogenerated documentation\n\n**EasyPeasy** is a well documented framework and therefore all the documented\nclasses and methods are available in [Cocoadocs](http://cocoadocs.org/docsets/EasyPeasy).\n\n## Author\n\nCarlos Vidal - [@nakiostudio](https://twitter.com/nakiostudio)\n\n## License\n\nEasyPeasy 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%2Fnakiostudio%2Feasypeasy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnakiostudio%2Feasypeasy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnakiostudio%2Feasypeasy/lists"}