AutoLayoutトルツメをコードで実装

環境
Xcode8.2
Swift3

## やりたいこと

横並びにあるオブジェクトを表示非表示を切り替え、非表示にしたオブジェクトを詰めて表示したい。
参考文献：[よくわかるAutoLayout本](https://www.amazon.co.jp/%E3%82%88%E3%81%8F%E3%82%8F%E3%81%8B%E3%82%8BAuto-Layout-iOS%E3%83%AC%E3%82%B9%E3%83%9D%E3%83%B3%E3%82%B7%E3%83%96%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%82%92%E3%83%9E%E3%82%B9%E3%82%BF%E3%83%BC-%E5%B7%9D%E9%82%89-%E9%9B%84%E4%BB%8B/dp/4865940324)


<img width="375" alt="Simulator Screen Shot 2017.02.02 16.25.54.png" src="https://qiita-image-store.s3.amazonaws.com/0/100514/3bb5f90f-964b-8922-9550-cfc45c77ec79.png">


例えば上記スクリーンショットにある `HogeButton` を非表示にすると、下記スクリーンショットのように `HogeButton` を非表示にし、UIButtonがあった空間を詰めて表示したい。


<img width="375" alt="Simulator Screen Shot 2017.02.02 16.26.02.png" src="https://qiita-image-store.s3.amazonaws.com/0/100514/35c96b73-c998-3d05-9e98-1bfdea156bae.png">


## 失敗例

Hiddenをfalseにするだけだとオブジェクトは非表示にはなりますが空間が残りました。

``` swift

UIButton.isHidden =  true

```


![Simulator Screen Shot 2017.02.02 16.29.45.png](https://qiita-image-store.s3.amazonaws.com/0/100514/ef1a016f-f39c-8920-d771-19324a5ea541.png)


## 制約を追加する

### Intrinsic sizeで決まる横幅を0にする制約を追加します

横幅を0にする制約を定義しておいたうえで、非表示にするタイミングでこの制約を追加。表示するタイミングで制約を削除します。

``` swift
        // ボタンの横幅を0にする制約
     let buttonWidthConstraint = NSLayoutConstraint(
            item: self.button
            , attribute: NSLayoutAttribute.width
            , relatedBy: NSLayoutRelation.equal
            , toItem: nil
            , attribute: NSLayoutAttribute.width
            , multiplier: 1.0
            , constant: 0)
```

### オブジェクト間の幅制約をIBOutletで接続

Storyboardから制約をドラッグしてファイルに追加します。
![スクリーンショット 2017-02-02 16.50.44.png](https://qiita-image-store.s3.amazonaws.com/0/100514/5c8b0160-222c-9462-71ed-c409731a3ec5.png)

IBOutletで接続できると下記のようにファイルにコードが生成されます。名前は `buttonLeadingConstraint` にしました

![スクリーンショット 2017-02-02 16.52.36.png](https://qiita-image-store.s3.amazonaws.com/0/100514/0479f73a-73ec-7ebb-7138-14fd521df409.png)

### 表示非表示のタイミングで制約を変更する

```swift
        if button.isHidden {
            // IBOutletで接続した制約
            buttonLeadingConstraint.constant = 8
            // 制約を削除する
            NSLayoutConstraint.deactivate([buttonWidthConstraint])
            button.isHidden = false
        }
        else {
            buttonLeadingConstraint.constant = 0
            // 制約を追加する
            NSLayoutConstraint.activate([buttonWidthConstraint])
            button.isHidden = true
        }
    }
```

### まとめ

非表示、表示のタイミングで制約を変更することで期待通りの動作が実装できました。
こうした方が良い方法があればご教示下さいmm


<img width="375" alt="Simulator Screen Shot 2017.02.02 16.26.02.png" src="https://qiita-image-store.s3.amazonaws.com/0/100514/eba7a620-93b1-abb3-5bf8-fdea6f4c2c61.png">

```swift
//
//  ViewController.swift
//  IntrinsicTorutsumeSample
//
//  Created by { Kazunori } on 2017/02/02.
//  Copyright © 2017年 Yamamoto Kazunori. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var button: UIButton!
    @IBOutlet weak var label: UILabel!
    @IBOutlet weak var switchButton: UISwitch!
    
    @IBOutlet weak var buttonLeadingConstraint: NSLayoutConstraint!
    @IBOutlet weak var labelLeadingConstraint: NSLayoutConstraint!
    @IBOutlet weak var switchLeadingConstraint: NSLayoutConstraint!
    @IBOutlet weak var switchWidthConstraint: NSLayoutConstraint!
    
    var buttonWidthConstraint: NSLayoutConstraint!
    
    override func viewDidLoad() {
        // ボタンの横幅を0にする制約
        buttonWidthConstraint = NSLayoutConstraint(
            item: self.button
            , attribute: NSLayoutAttribute.width
            , relatedBy: NSLayoutRelation.equal
            , toItem: nil
            , attribute: NSLayoutAttribute.width
            , multiplier: 1.0
            , constant: 0)
    }
    
    @IBAction func pressToolbarLabel(_ sender: Any) {
        if label.text == nil {
            label.text = "HogeGehoString"
            labelLeadingConstraint.constant = 8
        }
        else {
            label.isHighlighted = true
            label.text = nil
            labelLeadingConstraint.constant = 0
        }
    }
    
    @IBAction func pressToolbarButton(_ sender: Any) {
        if button.isHidden {
            buttonLeadingConstraint.constant = 8
            NSLayoutConstraint.deactivate([buttonWidthConstraint])
            button.isHidden = false
        }
        else {
            buttonLeadingConstraint.constant = 0
            NSLayoutConstraint.activate([buttonWidthConstraint])
            button.isHidden = true
        }
    }
    
    @IBAction func pressToolbarSwitch(_ sender: Any) {
        if switchButton.isHidden {
            switchLeadingConstraint.constant = 8
            switchWidthConstraint.constant = 49
            switchButton.isHidden = false
        }
        else {
            switchLeadingConstraint.constant = 0
            switchWidthConstraint.constant = 0
            switchButton.isHidden = true
        }
    }
}


```

スクリーンショット内の他のオブジェクト表示、非表示を行うサンプルを作成しました。

https://github.com/kazTera/IntrinsicTorutsumeSample