はじめに
XcodeでiOSアプリ開発をする場合に、設定を切り替えたい場合はxcconfigという手段があるということをグダグダ書いておきます。
グダグダ書く理由は2つ
- ConfigurationはDebug/Releaseの2つでxcconfig分ければいいだけ
- SchemeでたかだかWeb APIの接続先が違うくらいの小さな設定を変えてしまうのはオーバーキル
極論を書くと「通信先を切り替えたいだけでSchemeを切り替えるのはGUIから設定を書き換えられても気が付かないリスクを孕んでいるのでオーバーキルしている」ということです。
記事を書くモチベーションは
- xcconfigに関する良い記事は多いんですが、なぜかそこまで浸透してるとは思えず、なぜか人はオーバーキルしてしまう
- 自分で設定してないプロジェクトでSchemeごとに設定を変えられると、差分がないということだけでも証明することが面倒
という感じで、いきあたりばったりでxcconfigについて書いてみます。間違いがあるかもしれません。お手数おかけしますがコメントにお願いします。
基礎
Xcodeでは、プロジェクトのビルド設定をプレーンテキストファイルで指定し、Configuration(DebugビルドやReleseビルド)ごとに異なる設定を指定できます。
以下、具体的にグダグダ書いておきます。
Configurationごとに読み込める
まず、Projectの下にターゲットがあり、それは複数のConfiguration(基本はDebugとReleaseのみ)が存在し、xcconfigがターゲットのConfigurationごとに利用できるというイメージです。
例を示します
この時点で、info.plistのパスも切り替えられるのでDebugとReleaseでinfo.plistが変更可能な設定は切り替えられます(がややこしくなるためそれはここでは説明しません)
xcconfigを別に用意する
実務的には2つの接続先だけでは足らず、「ステージング環境も試したいんじゃよ」となるでしょう。もちろんそういう場合xcconfigに書けばいいだけにするのがミスがないはずです。だったらstg.target.xcconfig
を用意し、debug.target.xcconfig
を置き換えたらいいだけです。
例を示します
大抵はDebugとRelease以外を作る理由はないと思います。なぜなら大抵は「Web APIのホストを変更したい」と結局は文字列を置き換えるだけでしょう。Debugビルドでステージング環境用のxcconfigを読み込めればいいだけです。
stg.target.xcconfig
など作らず、debug.target.xcconfig
はテキストファイなので内部のテキストを置き換えてもいいでしょう。
xcconfigの共通化
複数のxcconfigを用意すると、「stgとかdebugとかで共通のやつどうすんねん。DRYって知っとんのか」と思うかもしれません。.xcconfigは別の.xcconfigを読み込むことができますので、共通の設定はそちらに書くことが可能です。
例を示します
Projectにもxcconfigを設定できる
公式のリファレンスにもありますが、もう少し基礎について書いておくと、Projectにもそれぞれのxcconfigを用意することができます。
正直オーバーキルしそうな感じなので、もし必要があったら分けたらいいとは思います。上の例ではdebug.project.xcconfig
とrelease.project.xcconfig
としましたが、公式リファレンスだとDebugもReleaseもBaseSettings.xcconfig
を読み込んでいます。
まあ基礎を書いておくとそこから何か問題解決の手がかりがつかめるかもしれないので書き残しときます。
CocoaPodsのxcconfigを読み込む
もともとCocoaPodsはxcconfigファイルをConfigurationごとに自動生成し開発者へそれを使わせます。CocoaPodsが開発者へWorkspaceを利用させる意図はそれです。
つまり、自前でxcconfigを作るとCocoaPodsの生成したxcconfigと衝突します。そのため、自前のxccofigでCocoaPodsのxcconfigをincludeすることになります。
xcconfigの課題
GUIの設定を優先される
万能すぎに見えるxcconfigですが、Xcode上のGUIから同じ項目を変更した場合はそのGUIの設定を優先します。これは差分が見えづらいのでPRに紛れ込んだときに見のがしちゃう可能性があって知らないうちに設定ファイルとは違う挙動になるきっかけになります。
この課題を解決するとしたらCIでproject設定が.xcconfig以外から変えられてるぞって警告するとかブロックするとかでしょうかね。やってる人いたら教えて下さい。
おわりに
ConfigurationはDebug/Releaseの2つでxcconfig分ければいいだけ
私が想定外のことがあるのかもしれません。もしinfo.plistやxcconfigで設定が分けられないことがあればコメントで教えていただければと思います。
SchemeでたかだかWeb APIの接続先が違うくらいの小さな設定を変えてしまうのはオーバーキル
Schemeが変更できる階層は広く、これを分けてしまうとそれぞれのSchemeごとの差分はそれぞれの階層ごとの差分となり、私には差分を比較しづらいです。
- Scheme
- Project
- Target
- Configuration
- xcconfig
- Build options
- Configuration
- Target
- Project
たとえばWeb APIの接続先を変えたいだけなのに、Schemeでそれを変更するならその接続先AとBのDebugビルドの設定は別々になっててもいいの?とかそれに気がつけるの?っていう危惧をしています。
もちろん、XcodeGenなどを利用することでプロジェクト設定をコード化できるので、その場合はSchemeで分けることにはあんまり抵抗はないです。