AutoLayoutをSwiftで簡潔に記述できるSnappyを試してみた


AutoLayoutはコードで書くと記述が長くなって面倒ですよね。それで、少し前にAutoLayoutを簡潔に記述できるMasonryというのが出ていたのですが、久しぶりに見てみたら完全Swift対応版のMasonryが出ていたので、試してみました。

- [Masonry/Snappy](https://github.com/Masonry/Snappy)

## インストール

Swiftで書かれたライブラリにはcocoapodsのような便利なインフラがないので、手動でライブラリを追加していくことになります。

### gitsubmoduleを追加する

まず、プロジェクトのルートに移動して、`git submodule add https://github.com/Masonry/Snappy.git`をして、Snappyをgitのsubmoduleとして追加します。

### Snappy.xcodeprojを利用するXcodeに追加する

Xcodeを開いて、先ほどsubmoduleとしてダウンロードしたSnappyのディレクトリの中の、Snappy.xcodeprojをFine navigatorにドラッグして入れます。

![x1.png](https://qiita-image-store.s3.amazonaws.com/0/24041/a9e692d6-faa1-4f01-6b3b-0a76192f701f.png "x1.png")


こんな感じの見た目になります。

### Embedded Binariesとして追加する

XcodeのTarget > General にある、Embeded Binariesの+ボタンを押して、Snappy.frameworkを追加する。

![x2.png](https://qiita-image-store.s3.amazonaws.com/0/24041/f2e71bc5-5874-f317-ac15-2f6dab54c236.png "x2.png")


こんな感じの見た目になります。さて、設定が出来ました！

## Snappyを使ってViewの配置をしてみた

![x6.png](https://qiita-image-store.s3.amazonaws.com/0/24041/f444c1d9-84a4-6f74-0814-f9c7845bedb6.png "x6.png")


こんなビューをframeを使わず、Snappyだけで表現してみました。

### コード

``` swift
import UIKit
import Snappy

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // FULL SCREEN VIEW [BLUE]
        
        let blueView = UIView()
        blueView.backgroundColor = UIColor.blueColor()
        self.view.addSubview(blueView)
        
        blueView.snp_makeConstraints { make in
            make.edges.equalTo(self.view)
            return
        }
        
        // PADDING ALL EDGES [ORANGE]
        
        let orangeView = UIView()
        orangeView.backgroundColor = UIColor.orangeColor()
        self.view.addSubview(orangeView)
        
        let orangeViewPadding = UIEdgeInsetsMake(10, 10, 10, 10)
        orangeView.snp_makeConstraints { make in
            make.edges.equalTo(self.view).with.insets(orangeViewPadding)
            return
        }
        
        // VIEW ON PADDING VIEW [GREEN]
        
        let greenView = UIView()
        greenView.backgroundColor = UIColor.greenColor()
        orangeView.addSubview(greenView)
        
        let greenViewPadding = UIEdgeInsetsMake(0.0, 0.0, 150.0, 10.0)
        greenView.snp_makeConstraints { make in
            make.top.equalTo(orangeView.snp_top).with.offset(greenViewPadding.top)
            make.left.equalTo(orangeView.snp_left).with.offset(greenViewPadding.left)
            make.bottom.equalTo(orangeView.snp_bottom).with.offset(-greenViewPadding.bottom)
            make.right.equalTo(orangeView.snp_right).with.offset(-greenViewPadding.right)
            return
        }
    }
}

```

## 使い方

UIViewControllerの`viewDidLoad`で色のついたビューを配置することをイメージして下さい。

### 一つ上の階層のビューと上下左右同じにする

``` swift
let blueView = UIView()
blueView.backgroundColor = UIColor.blueColor()
self.view.addSubview(blueView)

blueView.snp_makeConstraints { make in
    make.edges.equalTo(self.view)
    return
}
```

### 一つ上の階層のビューから指定した距離をおいて配置する

``` swift
let orangeView = UIView()
orangeView.backgroundColor = UIColor.orangeColor()
self.view.addSubview(orangeView)

let orangeViewPadding = UIEdgeInsetsMake(10, 10, 10, 10)
orangeView.snp_makeConstraints { make in
    make.edges.equalTo(self.view).with.insets(orangeViewPadding)
    return
}
```

その他に、下記のようにviewのNSLayoutAttributeが取得できるので、様々な自由なコンストレイントを貼ることができます。

![x3.png](https://qiita-image-store.s3.amazonaws.com/0/24041/6670a507-6af7-3c5d-31fe-82414aa1e740.png "x3.png")


また、priorityの設定もできるので、ほとんどのこと（すべて）が表現できるのではないでしょうか？

## 今回試したサンプル

- [morizotter/MZRSnappySample](https://github.com/morizotter/MZRSnappySample)

下記のコマンドでsubmoduleも取得して下さい。

``` bash
git clone git@github.com:morizotter/MZRSnappySample.git
git submodule init
git submodule update
```

## 参考

- [Masonry/Snappy](https://github.com/Masonry/Snappy)

## 更新

- [Rename to Snap · a647c10 · Masonry/Snap](https://github.com/Masonry/Snap/commit/a647c102904e0e14199a2db2d82d8f556567f2f2) により、名称がSnappyからSnapに変更になったようです。それにともなって、importもSnappyではなく**Snap**となったようです。