XCodeでproduction/staging/developをTargetで切り替えて、APIも切り替える。

# XCodeでproduction/staging/developをTargetで切り替える

- 別に新機能でも何でもないですが、知らない人の参考になればと思い書きました。
- これよりもっといい方法があれば教えていただければと思います。

## やりたいこと
- ソース内にフラグを持たさずに、TargetでAPIなどを切り替える　＝＞　git管理してても差分なし!!!!!!!!!

## 新たにTargetを作成する
- 既存のTargetを右クリックし、Deplicateを押します。

<img width="588" alt="Screen Shot 2017-09-19 at 0.47.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/62822/76a7b109-4ac2-0ee7-a4dc-88ec53c016f4.png">

- `{元のプロゲクト名} copy` となるので、Dev{プロジェクト名}や、Stg{プロジェクト名}とします。


## Plistを複製する
- 同じくPlistも新たに作成します。複製してもいいですし、新たに作成してもいいです。

<img width="250" alt="Screen Shot 2017-09-19 at 0.53.44.png" src="https://qiita-image-store.s3.amazonaws.com/0/62822/3fb07050-210a-645f-0824-e8ea1bd75715.png">

- `Bundle display name` やその他の設定などをそれ用に変えると良いかもしれません。

## スキームを編集する
- ManagementSchemeを押します。

<img width="357" alt="Screen Shot 2017-09-19 at 22.46.46.png" src="https://qiita-image-store.s3.amazonaws.com/0/62822/b923ec3f-2b9c-d031-f853-dc2f11e8e475.png">

<img width="771" alt="Screen Shot 2017-09-19 at 22.49.11.png" src="https://qiita-image-store.s3.amazonaws.com/0/62822/32bed4db-1484-f1b9-8bcd-43da68d6b30d.png">

- {プロジェクト名} copyというスキームが自動作成されていますが、−で削除します。
- そして、再度＋で追加すると、Dev{プロジェクト名}や、Stg{プロジェクト名}としてスキームを登録できます。
- shared にもチェックを入れておきます。

## Plistを関連付ける
- 作成したTargetを選択し、build settingsから Plistを検索すると、Info.plistのPathが{プロジェクト名} copy.plist となっているので、自分で作成したplistファイルに書き換えます。

<img width="1100" alt="Screen Shot 2017-09-19 at 22.52.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/62822/f8f3f377-9ff7-c260-1d20-57fa4f1d7304.png">

- また、マクロ用の変数を追加してもいいと思います。

<img width="1012" alt="Screen Shot 2017-09-19 at 22.56.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/62822/26361036-e84e-ff70-b8a8-3717db6251dc.png">

- DEV=1 STAGING=1などするのがおすすめです。

## APIをPlistで管理して、APIを出し分ける
- これは完全に私の場合ですが、APIディレクトリを切ってそこにAPIのHOSTやバージョンを管理しています。
- 新規で、Plistを作成します。

- API.plist
<img width="1359" alt="Screen Shot 2017-09-19 at 23.00.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/62822/eada622b-6465-bd17-d95e-db225d1e589b.png">

- DevAPI.plit
<img width="1362" alt="Screen Shot 2017-09-19 at 23.01.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/62822/b687038c-dbce-18ea-28a8-b3ce19155b0f.png">

- 今は変わってないですが、APIバージョンのv2とか、dev用のHOSTとか書いておきます

## ConfigでAPI.plistを読む

```Config/Config.swift
struct Config {
    static let host         = Config.plist(property: "host")
    static let version      = Config.plist(property: "version")
    static let mode         = Config.plist(property: "api")
    static let socket       = Config.plist(property: "socket")
    static let bundleID     = Bundle.main.bundleIdentifier ?? Config.host
    #if DEMO
    static let plistPath = "DemoApi"
    #elseif DEV
    static  let plistPath = "DevApi"
    #else
    static let plistPath = "Api"
    #endif
    static let realmAccessToken: String = MonaKeys().realmAccessToken() ?? ""
    
    static func plist(property: String) -> String {
        let pat = Config.plistPath
        guard let path = Bundle.main.path(forResource: pat, ofType: "plist") else { return "" }
        var dict = NSDictionary(contentsOfFile: path) as? [String: Any]
        if let string = dict?.removeValue(forKey: property) as? String {
            return string
        }
        return ""
    }
}
```

- 結局のところはここで出し分けているので、APIをPlistにする意味はあまりないんですねどね。

## まとめ
- 重要なのはTargetを切り替えて、そこでマクロを使って書き換えることができます。
- フラグなどで切り替えてもいいですが、ソースコードの改変が生じるのでそこをなくせます。
- また、読み込みたいソースなども切り替えられるので規模が大きくなると便利かと思います。
- 以上、swift関連の記事はまさかりが多く飛んできそうで怖いですが、[1000いいねチャレンジ](https://qiita.com/okamu_/items/0b7c752fb809b3506704)の一環として書かせていただきました。ありがとうございました。