チーム内でカラーパレットを共有して色を管理する方法（Xcode・iOS）

iPhoneアプリのチーム開発で問題になるのが、「色」
できれば、カラーパレットとソースコードを一括して管理したい。
色をチームで共有するためにやったことを、まとめてみます。

※ いろいろ方法があるようなので、One of them、1つの事例として。
※ 半年前くらいにやったことなので、途中抜けていたらすみません

# 前提条件

* **Objective-Cを使用するプロジェクト**であること（Swift混在可）。  
Swiftオンリーのプロジェクトなら、R.swiftを導入するのが良いかと。
* デザイン指示書などで色が指定されていない、もしくは、そもそもデザイン指示書がない

# 方針

* ソースコードで、`UIColor.mycolor()`みたいな感じで指定したい（AndroidのR.java的な）
* ソースコードとカラーパレットを一括して管理したい（同じ名前で使いたい）
* パレットファイルを渡し合うようなことはしたくない（手間）
* 色は、テキストで管理したい（扱いやすく）

# 手続き
## ColorToolsを導入

[ColorTools](https://github.com/ramonpoca/ColorTools)という便利ツールがあったので、これを使ってみることにしました。

（作業内容）

* ColorToolsをローカルにクローン
* そのディレクトリで、`sh mkrelease.sh 0.2` する（なお、`0.2`はバージョン数字、適当に）
* `build/Release`に作成された`Html2Clr`と`Clr2Obj`を、プロジェクトの適当な場所にコピーし、git管理下に入れる

ここでは、`~/MyApp/App/Scripts`に入れることにします。

ここまでの作業をまとめると、以下の通り。

```bash
$ git clone https://github.com/ramonpoca/ColorTools.git
$ cd ColorTools
$ sh mkrelease.sh 0.2
$ cp build/Release/Html2Clr ~/MyApp/App/Scripts
$ cp build/Release/Clr2Obj ~/MyApp/App/Scripts
```

## 色管理用のテキストファイルを用意する

拡張子はなんでも良い。プロジェクトのディレクトリに適当なテキストファイルを用意します。
ここでは、`~/MyApp/App/Resources/AppColors.txt`とします。

最終的にこのテキストファイル名でObjective-Cのクラス（UIColorのカテゴリ拡張）が出力されるので、それを念頭に決めて下さい。

内容例は、以下に。

```text:AppColors.txt
FFFFFF Background Color
000000 Body Text
9A9A9A Link Text
FB0007 Accent Color
FED10A Favorite Button
```

スクリプトは後ほど書きますが、これを`Html2Clr`でパレット化したものが、下の画像です。

![スクリーンショット 2017-04-13 15.04.18.png](https://qiita-image-store.s3.amazonaws.com/0/75329/451af200-07b3-481b-ec22-3e11ae730a57.png)

ひとまず、ここまでで、テキストで色管理ができるようになりました。

## ColorToolsを使用して、UIColorのカテゴリ拡張を生成する

では、上で作成したテキストファイルから、Objective-Cにはなりますが、UIColorのextentionを生成します。基本的にコマンド2つなので、まるっとそのまま載せます。
後ほど、自動化しますので、ここはテストランということで。

※Html2ClrとClr2Objは、`~/MyApp/App/Scripts`にある前提です。

```bash
$ cd ~/MyApp/App/
$ ./Scripts/Html2Clr ./Resources/AppColors.txt
$ ./Scripts/Clr2Obj ./Resources/AppColors.clr
$ ls Resources
AppColors.txt   AppColors.clr   UIColor+Appcorlors.h    UIColor+Appcolors.m
```

* `Html2Clr`に、`AppColors.txt`を食わせて、パレットファイルを出力
* `Clr2Obj`に、`AppColors.clr`を食わせて、Objective-Cファイルを出力

※エラーは出ますが、Objective-Cのファイルは出力されているので、問題ありません（たぶん）

さて、出力されたObjective-Cファイルは……こんな感じ。

```objc:Appcolors.h
#import <UIKit/UIKit.h>
@interface UIColor (Appcolors)
+ (UIColor *) backgroundColor;
+ (UIColor *) bodyText;
+ (UIColor *) linkText;
+ (UIColor *) accentColor;
+ (UIColor *) favoriteButton;

@end
```

```objc:Appcolors.m
#import "UIColor+Appcolors.h"

@implementation UIColor (Appcolors)
+ (UIColor *) backgroundColor {
    return [UIColor colorWithRed:1.000000 green:0.999974 blue:0.999991 alpha:1.000000];
}

+ (UIColor *) bodyText {
    return [UIColor colorWithRed:0.000000 green:0.000000 blue:0.000000 alpha:1.000000];
}

+ (UIColor *) linkText {
    return [UIColor colorWithRed:0.533880 green:0.533864 blue:0.533873 alpha:1.000000];
}

+ (UIColor *) accentColor {
    return [UIColor colorWithRed:0.966448 green:0.000000 blue:0.044851 alpha:1.000000];
}

+ (UIColor *) favoriteButton {
    return [UIColor colorWithRed:0.990845 green:0.788645 blue:0.056591 alpha:1.000000];
}

@end
```

必要なファイル類はこれで出来上がりました！

## ビルドフェーズに組み込んで自動化する

あとは、プロジェクトのBuild Phasesにスクリプトを組み込んで、自動化します。
こうすることで、ビルドの度にパレットファイルを同期させることができます。

```
1. Xcodeでプロジェクトを選択
2. Build Phasesに移動
3. 「+」を押して、ビルドフェーズを追加
4. Shell欄には「/bin/sh」、その下に、スクリプトを入力
```

ざっくり以下のようなスクリプトを組み込みます。

```
cd ${SRCROOT}
./Scripts/Html2Clr Resources/AppColors.txt
cp -f AppColors.clr ${HOME}/Library/Colors/AppColors.clr
./Scripts/Clr2Obj Resources/Colors.clr
```

重要なのは、**`cp -f`**でパレットファイルをユーザのライブラリにコピーするところ。
**`-f`**を入れておかないと上書きできないので、ビルドが落ちます。

最後に、作業ディレクトリだった`SRCROOT`に生成された`UIColor+Appcolors`のクラスを、使いやすいところに移動したらOKです。Bridging-Header.hに、このカテゴリ拡張を追加しておけば、Swiftクラスからも使用することができます。

# まとめ

iOSプロジェクトの色管理の手法についてまとめました。
テキストファイルで色を定義し、カラーパレットとUIColorの拡張を生成することで、ソースコードとInterface Builderで扱う色の名前を統一することができました。

なお運用には、以下の内容をチームに周知／徹底することが大切です。

* 色を追加するときは、まず色定義をファイルに書く
* この方法だとパレットからテキストへの反映はできない
* 1回ビルドしないと、パレットに反映されない

もちろん、R.swiftが使いやすいとは思いますが、これも一つの手法としてお役に立てるのではないでしょうか。

以上です。