Xcode, Interface Builder, Storyboardの小技をちょろっと紹介してみる

## Interface Builderで使えるカスタムカラーパレットを作成する (カラー定義)

コードでカラー定義する場合は、

```Swift:UIColor+Additions.swift
// Color palette
extension UIColor {
  @nonobjc class var primary: UIColor {
    return UIColor(red: 55.0 / 255.0, green: 0.0 / 255.0, blue: 179.0 / 255.0, alpha: 1.0)
  }
  @nonobjc class var secondary: UIColor {
    return UIColor(red: 3.0 / 255.0, green: 218.0 / 255.0, blue: 198.0 / 255.0, alpha: 1.0)
  }
}
```

というようにUIColorのextensionでカラーパレットを作成するのがよいだろう。

Interface Builderで使えるカラー定義は、

①カラーパネルを開いて、カラーパレットを選択する。

<img width="221" alt="スクリーンショット 2018-12-21 15.40.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/151693/d62d04d6-a937-a09e-0f5d-89a5eadb59c0.png">

②設定から"NEW"を選択するとカスタムカラーパレットが作成できる。

<img width="221" alt="スクリーンショット 2018-12-21 15.42.42.png" src="https://qiita-image-store.s3.amazonaws.com/0/151693/5036cf8c-c022-39e3-0d22-2c3a5d1aed10.png">

③必要に応じて作成したカラーパレットの名前と定義するカラー名を編集する。カラーパレット名は設定から編集することができるので、プロジェクト名などと一緒にしておくとわかりやすいだろう。

<img width="221" alt="スクリーンショット 2018-12-21 15.44.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/151693/68c25f46-a362-59f9-2a39-ef12d2069667.png">

④最終的にはこんな感じ。

<img width="221" alt="スクリーンショット 2018-12-21 15.45.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/151693/72c38d39-ec3f-43e9-36c1-595dd8110829.png">

作成したカスタムカラーパレットは、```~/Library/Colors/```配下に```Example.clr```といったファイル名で保存されているので、こちらをプロジェクトメンバーと共有することもできる。

## Asset Catalogでベクター画像を扱う

Asset Catalogで画像を管理する場合、一般的には解像度の異なるデバイス用に、それぞれのデバイスに合った解像度の画像を複数種類用意して設定する。この方法だと画像を用意する手間も多いし、サイズを間違えるなどのミスも発生しやすくなる。

Xcode 9から、Asset Catalogでベクター画像を扱えるようになっている。用意するのはPDFのベクター画像で、@1xのサイズで作成する。ベクター画像を扱えることのメリットとして、

1. **解像度ごとに画像を用意しなくて済むので、画像変更やサイズ変更時の対応が容易になる。**
2. **ビルド時にXcodeが@1x, @2x, @3xの画像ファイルを生成するので、にじみのないきれいな画像を表示することができる**

と挙げられ、画像リソース管理が大変な従来の方法よりも優位性が高い。設定手順と注意点としては、

①"Preserve Vector Data"にチェックする。

②"Scales"に"Single Scale"を設定する。

<img width="536" alt="スクリーンショット 2018-12-21 16.41.09.png" src="https://qiita-image-store.s3.amazonaws.com/0/151693/d7277be1-91c7-d6e1-83c1-05438c2188c0.png">

最終的にはこんな感じ。

<img width="536" alt="スクリーンショット 2018-12-21 17.36.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/151693/b52191dc-198c-2a7f-a2b6-09b83fcce8f8.png">

## Asset Catalogで拡縮する画像を設定する

Androidの9-patch的なアレ。コードでは、

```Swift
let image = UIImage(named: "Button")?.resizableImage(withCapInsets: UIEdgeInsets(top: , left: 10, bottom: 10, right: 10))
```

こうなるヤツ。Asset Catalogでコレを設定することができる。

①"Show Slicing"を選択する

<img width="536" alt="スクリーンショット 2018-12-21 17.36.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/151693/270ebebe-8da7-59b7-0268-f6ecf2e2a465.png">

②"Start Slicing"を選択し、拡縮する方向と範囲を設定する。

<img width="536" alt="スクリーンショット 2018-12-21 17.51.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/151693/051759af-c778-5844-ab04-5727f969aac8.png">

③"←・→"を選択するとこうなる。

<img width="536" alt="スクリーンショット 2018-12-21 17.52.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/151693/3a8d1fe9-8803-cf8f-8d89-d958bfc419b9.png">

コレでUIButtonやUIImageViewのサイズに応じて、横方向に拡縮されて表示されるようになる。

## AutoLayoutで配置されたViewをアニメーションさせる

Viewのframeを変更するのではなく、AutoLayoutで配置されたViewをアニメーションさせる方法。

以下のようにIBで配置されている"View"の"制約"を、コード側の変数とIBOutletで紐づけする。

<img width="700" alt="スクリーンショット 2018-12-21 19.12.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/151693/dadfdddd-a2df-cf35-b7e0-faef0980f713.png">

```Swift:ViewController.swift
import UIKit

class ViewController: UIViewController {
    
    @IBOutlet weak var topLayoutConstraint: NSLayoutConstraint!
    @IBOutlet weak var leadingLayoutConstraint: NSLayoutConstraint!

    override func viewDidLoad() {
        
        super.viewDidLoad()
        
    }
    
}
```

"Animation"ボタンが押されたときに、制約の値をアニメーションで変更するようにした。

```Swift:ViewController.swift
import UIKit

class ViewController: UIViewController {
    
    @IBOutlet weak var topLayoutConstraint: NSLayoutConstraint!
    @IBOutlet weak var leadingLayoutConstraint: NSLayoutConstraint!

    override func viewDidLoad() {
        
        super.viewDidLoad()
        
    }
    
    @IBAction func animationButtonTouchUpInside(_ sender: Any) {
        
        self.topLayoutConstraint.constant = 150
        self.leadingLayoutConstraint.constant = 100
        
        UIView.animate(withDuration: 0.3) {
            self.view.layoutIfNeeded()
        }
        
    }
    
}
```

ポイントとしては、制約の変更を適用させるメソッド、```layoutIfNeeded()```をアニメーション処理の中で呼ぶことである。