AssetCatalogに追加されたColorSetについて

#はじめに

Xcode9の正式版がリリースされてから約3ヶ月経ちますが、皆さんは追加された新機能を使用していますか？
今回は、追加された機能のうちの"ColorSet"について調べてみたので、備忘録として投稿してみようと思います。
なお、Qiita初投稿となります。生温かい目でネットリ見守って頂けると幸いです。

#そもそもColorSetとは
[Xcode Release Notes](https://developer.apple.com/library/content/releasenotes/DeveloperTools/RN-Xcode/Chapters/Introduction.html#//apple_ref/doc/uid/TP40001051-CH1-SW878)によると、


>Asset Catalog
>
>New Features
>Asset catalogs now support named colors that can be used in source files and Interface Builder. (28900538)

Xcode9.0から、ソースコード上やIB上から使用できる色定義が作成できるようになった、とのこと。
使用するにはBuild TargetをiOS11以上にする必要があるようです。

#色定義の作り方

1. AssetCatalogファイルを選択します
2. 画面左下の「＋」ボタンを押し、メニューを表示します。
3. メニュー内の「New Color Set」を選択します。

![スクリーンショット 2017-12-07 23.16.15.png](https://qiita-image-store.s3.amazonaws.com/0/105182/eaa4b597-6c6d-742c-db04-7f5090ec33fd.png)

これで、「Color」という名前の色定義が新たに作成されます。
![スクリーンショット 2017-12-07 23.33.58.png](https://qiita-image-store.s3.amazonaws.com/0/105182/5cb883e9-e373-61dc-0509-b62204ea06a5.png)

- 画像左側エディタエリアで、**ColorSetの名前**を変更することができます。
- 画像右側ユーティリティエリアで、**Color Space**や**Input Method**を変更することができます。**Color**で直接色を指定することもできます。

#実際に使ってみた

今回は

- Redを0.4 Greenを0.7 Blueを1.0で定義したLightBlue
- Redを1.0 Greenを0.7 Blueを0.4で定義したLightOrange

を作ってみました。
![スクリーンショット 2017-12-07 23.56.36.png](https://qiita-image-store.s3.amazonaws.com/0/105182/2934c968-b45d-d00c-4cf8-6e0b159c6444.png)

InterfaceBuilderで使用する場合、色を指定する際に「Named Colors」の欄が追加されており、そこから選択できるようになっています。

![スクリーンショット 2017-12-08 0.00.55.png](https://qiita-image-store.s3.amazonaws.com/0/105182/b4c07f11-c838-ddcc-f2d6-2adb972909a2.png)

ソースコードで使用する場合は[以下のイニシャライザ](https://developer.apple.com/documentation/uikit/uicolor/2877380-init)を使うようです。

```UIColor.swift:
extension UIColor {

    @available(iOS 11.0, *)
    public /*not inherited*/ init?(named name: String) // load from main bundle

    @available(iOS 11.0, *)
    public /*not inherited*/ init?(named name: String, in bundle: Bundle?, compatibleWith traitCollection: UITraitCollection?)
}
```

#データ構造
##AssetCatalogデータ
まずColorSetを作成するとAssets.xcassets内に`<色定義名>.colorset/Contents.json`というファイルが作成されます。先程作成した**LightBlue**の場合、以下のようになります。

```Assets.xcassets/LightBlue.colorset/Contents.json
{
  "info" : {
    "version" : 1,
    "author" : "xcode"
  },
  "colors" : [
    {
      "idiom" : "universal",
      "color" : {
        "color-space" : "srgb",
        "components" : {
          "red" : "0.400",
          "alpha" : "1.000",
          "blue" : "1.000",
          "green" : "0.700"
        }
      }
    }
  ]
}
```
なお、**Input Method**の情報は`"color-space"`のようには保持しておらず、上記のColorSetの設定を`FloatingPoint(0.0-1.0)`から`８bit(0-255)`に変更すると

```Assets.xcassets/LightBlue.colorset/Contents.json
{
  "info" : {
    "version" : 1,
    "author" : "xcode"
  },
  "colors" : [
    {
      "idiom" : "universal",
      "color" : {
        "color-space" : "srgb",
        "components" : {
          "red" : "102",
          "alpha" : "1.000",
          "blue" : "255",
          "green" : "178"
        }
      }
    }
  ]
}
```
となりました。また、`8-bit(Hexadecimal)`にした場合は`"red" : "0x66"`のようになります。

##InterfaceBuilderでのデータ
`ViewController`の`View`の背景色に`WhiteColor`をセットした状態から、先程定義した`LightBlue`に変更してみると、以下のような差分が出ます。

```diff
@@ -6,6 +6,7 @@
     <dependencies>
         <deployment identifier="iOS"/>
         <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13527"/>
+        <capability name="Named colors" minToolsVersion="9.0"/>
         <capability name="Safe area layout guides" minToolsVersion="9.0"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
@@ -17,7 +18,7 @@
                     <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
                         <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
                         <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
-                        <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+                        <color key="backgroundColor" name="LightBlue"/>
                         <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
                     </view>
                 </viewController>
@@ -25,4 +26,9 @@
             </objects>
         </scene>
     </scenes>
+    <resources>
+        <namedColor name="LightBlue">
+            <color red="0.40000000000000002" green="0.69803921568627447" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+        </namedColor>
+    </resources>
 </document>
```
設定した時点で、色の内容のコピーが作成される様ですね。

#残念なところ
##その１
AssetCatalogとInterfaceBuilderを両方開いた状態でAssetCatalogの色を変更しても、InterfaceBuilderの表示には反映されませんでした。ただし、ビルドすると反映されていました。
![スクリーンショット 2017-12-08 1.39.59.png](https://qiita-image-store.s3.amazonaws.com/0/105182/39e9c2cf-019c-4c45-a984-da7bcdcb9355.png)

一度プロジェクトを閉じ、再度開くと、InterfaceBuilder上に反映されていました。もちろんビルドした画面にも反映されていました。
![スクリーンショット 2017-12-08 1.41.37.png](https://qiita-image-store.s3.amazonaws.com/0/105182/45413d31-f50a-00b7-a34f-f84c23c54f32.png)

##その２
「その１」の操作を行った時、`Main.storyboard`に差分が一切発生しませんでした。つまり、色の内容のコピーは、InterfaceBuilder上で設定したタイミングに作成され、AssetCatalogの定義に追従して変更してくれるわけではない模様です。
そのため、「その１」の後にAssetCatalogの定義を消してみたところ、コピーが作成された時点のオレンジ色が表出してしまいました。
![スクリーンショット 2017-12-08 2.18.10.png](https://qiita-image-store.s3.amazonaws.com/0/105182/f7d28fb8-4c20-87df-44cd-25a8eb21c115.png)


色定義を変更する場合や削除する場合、`grep`をかけてあげるなど、工夫が必要がそうです。

#おわりに
Xcode9から追加された**safe area**など、完全に理解できていない要素がまだまだたくさんあるため、今後はそちらについても勉強していこうと思っています。