diff --git a/README.md b/README.md index 348857d..ed277b6 100644 --- a/README.md +++ b/README.md @@ -1,351 +1,34 @@ + -
- SnapKit -
- -==== +SnapKit is a DSL to make Auto Layout easy on both iOS and OS X. [![Build Status](https://travis-ci.org/SnapKit/SnapKit.svg)](https://travis-ci.org/SnapKit/SnapKit) -SnapKit is a light-weight layout framework which wraps AutoLayout with a nicer syntax. SnapKit has its own layout DSL which provides a chainable way of describing your NSLayoutConstraints which results in layout code that is more concise and readable. SnapKit supports both iOS and OS X. - -> SnapKit uses some Swift-only features like function overloading, so it cannot be used from Objective-C. Because of this we’ve chosen to swap prefixes from Masonry’s `mas_` to `snp_` so you can use both Masonry and SnapKit in the same project. - -## Requirements - -* iOS 7.0+ / Mac OS X 10.9+ -* Xcode 6.1 - -## Installation - -> **Embedded frameworks require a minimum deployment target of iOS 8 or OS X Mavericks.** - -### CocoaPods - -[CocoaPods](http://cocoapods.org) is a dependency manager for Cocoa projects. - -CocoaPods 0.36 adds supports for Swift and embedded frameworks. You can install it with the following command: - -```bash -$ gem install cocoapods -``` - -To integrate SnapKit into your Xcode project using CocoaPods, specify it in your `Podfile`: - -```ruby -source 'https://github.com/CocoaPods/Specs.git' -platform :ios, '8.0' -use_frameworks! - -pod 'SnapKit', '~> 0.10.0' -``` - -Then, run the following command: - -```bash -$ pod install -``` - -### Carthage - -Carthage is a decentralized dependency manager that automates the process of adding frameworks to your Cocoa application. - -You can install Carthage with [Homebrew](http://brew.sh/) using the following command: - -```bash -$ brew update -$ brew install carthage -``` - -To integrate SnapKit into your Xcode project using Carthage, specify it in your `Cartfile`: - -``` -github "SnapKit/SnapKit" >= 0.10.0 -``` - -### Manually - -If you prefer not to use either of the aforementioned dependency managers, you can integrate SnapKit into your project manually. - -### Embedded Framework - -- Add SnapKit as a [submodule](http://git-scm.com/docs/git-submodule) by opening the Terminal, `cd`-ing into your top-level project directory, and entering the following command: - -```bash -$ git submodule add https://github.com/SnapKit/SnapKit.git -``` - -- Open the `SnapKit` folder, and drag `SnapKit.xcodeproj` into the file navigator of your app project. -- In Xcode, navigate to the target configuration window by clicking on the blue project icon, and selecting the application target under the "Targets" heading in the sidebar. -- Ensure that the deployment target of SnapKit.framework matches that of the application target. -- In the tab bar at the top of that window, open the "Build Phases" panel. -- Expand the "Target Dependencies" group, and add `SnapKit.framework`. -- Click on the `+` button at the top left of the panel and select "New Copy Files Phase". Rename this new phase to "Copy Frameworks", set the "Destination" to "Frameworks", and add `SnapKit.framework`. - -## What's wrong with NSLayoutConstraints? - -Under the hood Auto Layout is a powerful and flexible way of organising and laying out your views. However creating constraints from code is verbose and not very descriptive. -Imagine a simple example in which you want to have a view fill its superview but inset by 10 pixels on every side ```swift -let superview = self; +import SnapKit -let view1 = UIView() -view1.setTranslatesAutoresizingMaskIntoConstraints(false) -view1.backgroundColor = UIColor.greenColor() -superview.addSubview(view1) +class MyViewController: UIViewController { -let padding = UIEdgeInsetsMake(10, 10, 10, 10) - -superview.addConstraints([ - NSLayoutConstraint( - item: view1, - attribute: NSLayoutAttribute.Top, - relatedBy: NSLayoutRelation.Equal, - toItem: superview, - attribute: NSLayoutAttribute.Top, - multiplier: 1.0, - constant: padding.top - ), - NSLayoutConstraint( - item: view1, - attribute: NSLayoutAttribute.Left, - relatedBy: NSLayoutRelation.Equal, - toItem: superview, - attribute: NSLayoutAttribute.Left, - multiplier: 1.0, - constant: padding.left - ), - NSLayoutConstraint( - item: view1, - attribute: NSLayoutAttribute.Bottom, - relatedBy: NSLayoutRelation.Equal, - toItem: superview, - attribute: NSLayoutAttribute.Bottom, - multiplier: 1.0, - constant: -padding.bottom - ), - NSLayoutConstraint( - item: view1, - attribute: NSLayoutAttribute.Right, - relatedBy: NSLayoutRelation.Equal, - toItem: superview, - attribute: NSLayoutAttribute.Right, - multiplier: 1.0, - constant: -padding.right - ) -]) -``` -Even with such a simple example the code needed is quite verbose and quickly becomes unreadable when you have more than 2 or 3 views. -Another option is to use Visual Format Language (VFL), which is a bit less long winded. -However the ASCII type syntax has its own pitfalls and its also a bit harder to animate as `NSLayoutConstraint.constraintsWithVisualFormat` returns an array. - -## Prepare to meet your Maker! - -Heres the same constraints created using ConstraintMaker - -```swift -let padding = UIEdgeInsetsMake(10, 10, 10, 10) - -view1.snp_makeConstraints { (make) -> Void in - make.top.equalTo(superview.snp_top).offset(padding.top) - make.left.equalTo(superview.snp_left).offset(padding.left) - make.bottom.equalTo(superview.snp_bottom).offset(-padding.bottom) - make.right.equalTo(superview.snp_right).offset(-padding.right) -} -``` -Or even shorter - -```swift -view1.snp_makeConstraints { (make) -> Void in - make.edges.equalTo(superview).insets(padding) -} -``` - -Also note in the first example we had to add the constraints to the superview `superview.addConstraints`. -SnapKit however will automagically add constraints to the appropriate view. - -SnapKit will also call `view1.setTranslatesAutoresizingMaskIntoConstraints(false)` for you. - -## Not all things are created equal - -> `.equalTo` equivalent to **NSLayoutRelation.Equal** - -> `.lessThanOrEqualTo` equivalent to **NSLayoutRelation.LessThanOrEqual** - -> `.greaterThanOrEqualTo` equivalent to **NSLayoutRelation.GreaterThanOrEqual** - -These three equality constraints accept one argument which can be any of the following: - -#### 1. ViewAttribute - -```swift -make.centerX.lessThanOrEqualTo(view2.snp_left) -``` - -ViewAttribute | NSLayoutAttribute -------------------------- | -------------------------- -view.snp_left | NSLayoutAttribute.Left -view.snp_right | NSLayoutAttribute.Right -view.snp_top | NSLayoutAttribute.Top -view.snp_bottom | NSLayoutAttribute.Bottom -view.snp_leading | NSLayoutAttribute.Leading -view.snp_trailing | NSLayoutAttribute.Trailing -view.snp_width | NSLayoutAttribute.Width -view.snp_height | NSLayoutAttribute.Height -view.snp_centerX | NSLayoutAttribute.CenterX -view.snp_centerY | NSLayoutAttribute.CenterY -view.snp_baseline | NSLayoutAttribute.Baseline - -#### 2. UIView/NSView - -if you want view.left to be greater than or equal to label.left : -```swift -// these two constraints are exactly the same -make.left.greaterThanOrEqualTo(label) -make.left.greaterThanOrEqualTo(label.snp_left) -``` - -#### 3. Strict Checks - -Auto Layout allows width and height to be set to constant values. -if you want to set view to have a minimum and maximum width you could pass a primitive to the equality blocks: -```swift -// width >= 200 && width <= 400 -make.width.greaterThanOrEqualTo(200) -make.width.lessThanOrEqualTo(400) -``` - -However Auto Layout does not allow alignment attributes such as left, right, centerY etc to be set to constant values. -So if you pass a primitive for these attributes SnapKit will turn these into constraints relative to the view’s superview ie: -```swift -// creates view.left <= view.superview.left + 10 -make.left.lessThanOrEqualTo(10) -``` - -You can also use other primitives and structs to build your constraints, like so: -```swift -make.top.equalTo(42) -make.height.equalTo(20) -make.size.equalTo(CGSizeMake(50, 100)) -make.edges.equalTo(UIEdgeInsetsMake(10, 0, 10, 0)) -make.left.equalTo(view).offset(UIEdgeInsetsMake(10, 0, 10, 0)) -``` - -## Learn to prioritize - -> `.prority` allows you to specify an exact priority - -> `.priorityHigh` equivalent to **UILayoutPriority.DefaultHigh** - -> `.priorityMedium` is half way between high and low - -> `.priorityLow` equivalent to **UILayoutPriority.DefaultLow** - -Priorities are can be tacked on to the end of a constraint chain like so: -```swift -make.left.greaterThanOrEqualTo(label.snp_left).priorityLow(); - -make.top.equalTo(label.snp_top).priority(600); -``` - -## Composition, composition, composition - -SnapKit also gives you a few convenience methods which create multiple constraints at the same time. - -#### edges - -```swift -// make top, left, bottom, right equal view2 -make.edges.equalTo(view2); - -// make top = superview.top + 5, left = superview.left + 10, -// bottom = superview.bottom - 15, right = superview.right - 20 -make.edges.equalTo(superview).insets(UIEdgeInsetsMake(5, 10, 15, 20)) -``` - -#### size - -```swift -// make width and height greater than or equal to titleLabel -make.size.greaterThanOrEqualTo(titleLabel) - -// make width = superview.width + 100, height = superview.height - 50 -make.size.equalTo(superview).offset(CGSizeMake(100, -50)) -``` - -#### center - -```swift -// make centerX and centerY = button1 -make.center.equalTo(button1) - -// make centerX = superview.centerX - 5, centerY = superview.centerY + 10 -make.center.equalTo(superview).offset(CGPointMake(-5, 10)) -``` - -You can chain view attributes for increased readability: - -```swift -// All edges but the top should equal those of the superview -make.left.right.bottom.equalTo(superview) -make.top.equalTo(otherView) -``` - -## Hold on for dear life - -Sometimes you need modify existing constraints in order to animate or remove/replace constraints. -In SnapKit there are a few different approaches to updating constraints. - -#### 1. References -You can hold on to a reference of a particular constraint by assigning the result of a constraint make expression to a local variable or a class property. -You could also reference multiple constraints by storing them away in an array. - -```swift - -var topConstraint: Constraint? = nil - -... - -// when making constraints -view1.snp_makeConstraints { make in - self.topConstraint = make.top.equalTo(superview).offset(padding.top).constraint - make.left.equalTo(superview).offset(padding.left) -} - -... -// then later you can call -self.topConstraint.uninstall() -``` - -### 2. snp_remakeConstraints - -`snp_remakeConstraints` is similar to `snp_makeConstraints`, but will first remove all existing constraints installed by SnapKit. - -```swift -func changeButtonPosition() { - self.button.snp_remakeConstraints { make in - make.size.equalTo(self.buttonSize) - - if topLeft { - make.top.left.equalTo(10) - } else { - make.bottom.equalTo(self.view).offset(-10) - make.right.equalTo(self.view).offset(-10) - } - } -} -``` - -## Code Snippets - -Copy the included code snippets to ``~/Library/Developer/Xcode/UserData/CodeSnippets`` to write your snap closures at lightning speed! - -`snp_make` -> `.snp_makeConstraints { make in }` + lazy var box = UIView() -`snp_remake` -> `.snp_remakeConstraints { make in }` + override func viewDidLoad() { + super.viewDidLoad() + + self.view.addSubview(box) + box.snp_makeConstraints { (make) -> Void in + make.width.height.equalTo(50) + make.center.equalTo(self.view) + } + } -## TODO +} +``` -* Eye candy -* Example projects -* Tests +## Resources + +* [Documentation](http://snapkit.io/docs/) +* [F.A.Q.](http://snapkit.io/faq/) + +## License + +MIT license. See the `LICENSE` file for details.