cocoapods-keysを複数人で使う方法(環境設定値のプロジェクトからの切り離し)

<!-- link refs -->
[cocoapods-keys_github]: https://github.com/orta/cocoapods-keys
<!-- -->

環境設定値をplistに書いたり、jsonに書いたり、リモートリポジトリにあがるソースコード内に出来る限り含めたくないと思って、cocoapods-keysを知り、更に複数人開発しているプロジェクトでcocoapods-keysを使えないかと調べたメモになります。

## TL;DR

- 環境設定値をプロジェクトから切り離したい、複数人開発でも共有できるようにしたい
- cocoapods-keysをとりあえず使ってみる
- `.env`ファイルを用意し、環境変数を宣言する
- Podfileに、cocoapods-keysのplugin記述を追加し、`pod install`時に`.env`から*key*を引っ張ってこれるようにする
- `pod install`を実行する
- あとはPodfileと.envファイルを共有すれば幸せになれる
- Dev,Stg,Prd毎に分けたい場合はちょっとだけ分岐処理が必要。


## cocoapods-keysとは

プロジェクトから環境に関する設定値(サービスのAccessKeyやSecretKey等)を切り離して管理するものとして、**cocoapods-keys**というCocoaPodsのプラグインがあります。
[https://github.com/orta/cocoapods-keys][cocoapods-keys_github]

こちらを使うことで、設定値をキーチェーンに保存し、プロジェクトから切り離すことができます。
こちらの導入、使用方法に関しては、@susieyy さんが書かれた記事にきれいにまとめられていますので、リンクを貼っておきます。
[cocoapods-keysで設定値をプロジェクトから切り離す](http://qiita.com/susieyy/items/4632e30068a826b936f6)

----

1人で使用する分には、キーチェーンに保存されるのはセキュアだし良いのですが、

- 複数人で開発しているプロジェクトで使用したい
- 人毎に各々のマシンのキーチェーンに登録してもらうのが大変&危険(登録ミス、更新ミス...etc)
- CircleCIなどでも使いたい
となったときに、キーチェーンに保存だと困ったことになります..><

複数人で使う時どうするのかなーって調べてもあまり詳しく出てこなかったので、
手順をまとめてみました。

ということで、本題に入ります。
一応拙いながら、インストールからの手順から書いていきます。
大事なのは、2,3番あたりになります。

話が変わりますが、ちょうどこの記事を書いている時に、株式会社スピカさんが、以下の記事を上げていましたので、こちらも読んでみるのもいいかもしれません。
[アプリの環境設定値を .env で管理する](http://qiita.com/sora0077@github/items/9976924df253016e42b4)

----

## 導入から、複数人共有まで
### 0.試した環境について

自分は以下の環境で試したので、参考になればと思います。

- Xcode: 7.1.1
- CocoaPods: 0.39.0
- cocoapods-keys: 1.6.0
- Ruby: 2.1.0

### 1. cocoapods-keysをインストール

```bash:Terminal
$ gem install cocoapods-keys
```

でインストールします。

もし、複数人で開発していて、CocoaPodsのバージョンをGemfile作って揃えたりしている場合なんかは、そちらに追加して、`bundle install`でついでに入れれば、複数人でcocoapods-keysのバージョンを揃えられるかと思います。
参考 : [iOS複数人で開発する時にこれだけはやっておけ](http://qiita.com/daisuke0131/items/52d5d8d3298c950ea613)

### 2. `.env`ファイルの準備
プロジェクトのルートに、`.env`ファイルを用意します。
例えばですが、以下のように、.envファイルに、必要な*key*と*value*を書いていきます。

```bash:Terminal
$ vim .env
```

```bash:.env
SomeAccessKey="xxxxxxxx-xxxxxxxx-xxxxxxxx-xxxxxxxx"
SomeSecretKey="xxxxxxxxxxxxxxxx"
```
shellなどで環境変数は大文字で書いて、`SOME_ACCESS_KEY`みたいにすることが多いかと思いますが、**[パスカルケース](https://ja.wikipedia.org/wiki/キャメルケース)**で書いておいたほうがいいかもしれないです。理由は後述します。

### 3. Podfileに追記する

次は、`Podfile`に、`.env`で書いた変数名と同じ名前のものを*key*として登録するための記述を追加します。
追加する場所は、Podfileの最後で大丈夫です。

```rb:Podfile
plugin 'cocoapods-keys', {
  :project => "プロジェクト名",
  :keys => [
    "SomeAccessKey",
    "SomeSecretKey"
]}
```

これで、`pod install`を実行した時に、対応する*key*を`.env`ファイルから読み込んで、追加してくれます。
あとは、

```bash:Terminal
$ pod install
# or pod update
```

成功していれば、*key*が登録され、プロジェクトに生成したファイルが追加されます。

`pod keys`
で登録したkeyの一覧を観ることができます(設定値は見れません。)

ワークスペース内に追加される場所は、
`Pods/CocoaPodsKeys`です。
(ワークスペース内で見ると、`Pods/Development Pods/Keys/`となっています。)

ためしに、生成されたファイルを覗くと...

```objc:生成物(Objective-C)
@interface SampleKeys : NSObject

- (NSString *)someAccessKey;
- (NSString *)someSecretKey;

@end
```

といった感じで生成されています。この時に、keyがキャメルケースになっているので、`SOME_ACCESS_KEY`って書くと`sOme_Access_Key`みたいになって、ちょっとおかしなことになります。笑

### 4. 複数人で開発している場合は...
あとは、`Podfile`と、`.env`ファイルをリポジトリに含めて共有し、
皆が`pod install`を実行すれば大丈夫です。

ただ、環境変数書いた`.env`をリモートに上げたくない！って場合は、`.gitignore`なりに、`.env`を追加して、手動で入れてもらう、等すれば良いかと思います。そのへんはおこのみで。

CocoaPodsを使っている時点で大丈夫だとは思いますが、`Pods/`は.gitignoreに指定しておけば最低限大丈夫です。

現時点では、Swiftであっても、生成されるKeysファイルは、**~~~Keys.h/.m**となります。

## 使用する

#### ・Objective-Cの場合

`#import <Keys/プロジェクト名Keys.h>`
でインポートします。プロジェクト名が、Sampleなら、
`#import <Keys/SampleKeys.h>`
となります。

```objc:AppDelegate.m(使用例)

#import <Keys/SampleKeys.h> //追加する

@interface AppDelegate ()
@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    SampleKeys *keys = [SampleKeys new]; //keysオブジェクトの生成
    NSLog(@"access key : %@",keys.someAccessKey);
    NSLog(@"secret key : %@",keys.someSecretKey);
    
    return YES;
}

...
```

間違ってもNSLog()なんかで吐き出さないようにしてください。



#### ・Swiftの場合

Swiftの場合は、`import Keys`を記述すれば、使用できるようになります。
クラス名等は、Objective-Cの場合と同じです。

```swift:AppDelegate.swift(使用例)
import Foundation
import UIKit

import Keys //追加する

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?


    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        let keys = SampleKeys() //keysオブジェクトの生成
        print(keys.someAccessKey())
        print(keys.someSecretKey())
        return true
    }
...
}
```

こちらも間違っても、print()しないように気をつけてください！


## 環境(Development,Staging,Production)等で分けたい場合は...

分岐処理はどうしても、自分で書いて用意する他なさそうです。
cocoapods-keysには、

- SomeAccessKeyDev
- SomeAccessKeyStg
- SomeAccessKeyPrd

のように分けて登録し、Swift Other Flagsに各環境のFlagを立てて、環境ごとに読み出すkeyを分岐するものを1回噛ます必要がありそうです。
Swift Other Flagsについての参考 : [Swift での #ifdef DEBUG のやり方](http://qiita.com/qmihara/items/a6b88b74fe64e1e05ca4)

```swift:Environment.swift

import Keys

struct Environment {

    private init() {}

    #if DEVELOPMENT
    static let someAccessKey = CocoapodskeysampleswiftKeys().someAccessKeyDev()
    #elseif STAGING
    static let someAccessKey = CocoapodskeysampleswiftKeys().someAccessKeyStg()
    #elseif PRODUCTION
    static let someAccessKey = CocoapodskeysampleswiftKeys().someAccessKeyprd()
    #else
    #endif
}

...

print(Environment.someAccessKey) // 環境に応じたkeyが出力される。
```

この件に関して、cocoapods-keysを使ってもっとスマートにいく方法があったら教えて下さい...!



----

長くなりましたが、お付き合いいただき、ありがとうございました(^^)/

## おまけ - トラブルシューティング的なもの
keyの名前がtypoしてたり、.envを編集して、.envやPodfileにはもう記述がなくて、
`pod keys`で表示されるkeyがあったりすると、`pod install`を実行した時にコケることがあります。
その時は、古いor誤ったkeyを削除して、再度実行したりするとうまくいきます。

```bash:Terminal
$ pod keys
# 出力例
Keys for Sample
 ├  SomeAccessKey -
 └  SomeSecretKey -
# 登録されているkeyを確認する

$ pod keys rm [key] #削除したいkeyを書く
# 実行例 : $ pod keys rm SomeAccessKey
[!] Removed value for key, and deleted associated key in Keychain.
```