マンガZERO(iOS)の開発環境の紹介
マンガZERO(iOS)では環境変数をScheme毎に変えてビルドできるようにしています。
この記事では環境変数を変える理由と実際にConfigファイルを使って環境変数を切り替える手段を紹介します。
社内配布限定のアプリを作りたいなどの要望があった場合、この手法ですぐに対応できるようになるのでオススメです。
マンガZERO(iOS)のSchemeの分け方
以下の3パターンに分けてアプリを生成できるようにしています。
- Debug
開発時用。開発者以外は触りません。 - Adhoc
社内配布用。新機能の使い心地やユーザビリティなどを確かめる際に使われています。
社内ではFabricのBetaを使用して、配布しています。 - Store
公開用。ストアに公開される状態をもつようにしています。
弊社ではiTunes ConnectのTestflightを使用して最終デバッグをしています。
上記のSchemeで以下の環境変数を分けて使用するようにしています。
- Bundle Identifier
- URL Scheme
- OTHER_SWIFT_FLUG
1つずつ値を説明します。
Bundle Identifer
アプリ固有識別IDになる値です。
この値はユニークでなくてはなりません。また同じIDを持ったアプリは同一アプリとしてデバイスにインストールされてしまいます。
なので、1つのデバイスにStore版とAdhoc版をインストールできるようにBundle Identifierを分けるようにしています。
Bundle Identifierを分けるようになった理由
余談ではありますが、Bundle Identifierを分ける理由を書いておこうと思います。
マンガZERO(iOS)ではユーザーがお気に入りした作品や読書履歴などの情報をRealmに保存するようにしています。
昔はAdhoc版もStore版も同じBundle Identifierだったため、新機能を実装したAdhoc版を入れる前にStore版を削除しなければならない作業が発生していました。
そしてアプリを削除するとRealmのデータも削除されていました。
しかしRealmのマイグレーション処理が正常に行われているかのテストをするためお気に入りなどをする必要があり、テストする前に無駄な作業が毎回発生しておりました。
そのため、Bundle Identifierを分けて別アプリとして扱うことで、アプリの再インストールの必要性がなくなり、アップデートを繰り返せるようになったのでデータが消えることもない状況になってデバッグや確認作業が格段に捗るようになりました。
URL Scheme
こちらもBundle Identifierの影響で別アプリにした結果、分ける必要が発生した値になります。
別アプリや計測時にAdhoc版とStore版が衝突しないように分けました。
OTHER_SWIFT_FLAG
こちらは以下の構文を使えるように分けています。
#if DEBUG
// Debug Schemeのビルドの時のみ実行したい
#endif
#if DEBUG || ADHOC
// Store Scheme以外のビルドで実行したい
#endif
主に分けるタイミングは以下になります。
- ログ出力
- 広告のテスト配信
ログ出力は開発時以外は出力したくないなどの理由で分けています。
広告のテスト配信については開発時には表示されることだけを知れれば良いので、広告側で用意していただいているTestIDを指定したり、デバイスを登録する処理を書いたりしています。
実際に分ける方法
ここからはスクショ等を用いて、実際に分ける処理の書き方を紹介したいと思います。
# 開発環境
Xcode: 8.3.3
Swift: 3.1
iOS Deployment Target: iOS8 ~
Base SDK: Latest iOS (iOS10.3)
上記の環境で作成しています。
GitHubのrepositoryも用意したので、説明がわかりづらかったら直接プロジェクトを開いてください。(そうならないように頑張ります)
設定の紹介の最後にCocoaPodsとの共存方法も書きましたので、合わせてご確認ください。
プロジェクト作成
アプリケーションであれば問題ないと思いますが、今回はSingle View Applicationで作成しました。
Configファイルの作成
作成したいディレクトリ(or Group)の上で右クリック > New File… > Other > Configuration Settings File を選択してください。
ファイル名は個人的にConfig.[環境].xcconfig
という名前にしています。
e.g )
– Debug : Config.Debug.xcconfig
– Adhoc : Config.Adhoc.xcconfig
– Store : Config.Store.xcconfig
ファイル名をConfig.Debug.xcconfig
にして生成すると以下のテキストが書かれたファイルが生成されます。
//
// Config.Debug.xcconfig
// \(プロジェクト名)
//
// Created by \(ユーザー名) on \(生成した時間).
// Copyright © 2017年 \(Author名). All rights reserved.
//
上記と同様にAdhocとStoreの.xcconfig
ファイルを作成します。
Configファイルの編集
試しにBundle Identifierを環境毎に変えてみたいと思います。
手順は2つあります。
.xcconfig
ファイルの編集.xcconfig
ファイルの指定と反映
xcconfigファイルの編集
Debug、Adhoc、Storeのファイルを以下のように編集します。
// Config.Debug.xcconfig
PRODUCT_BUNDLE_IDENTIFIER=com.example.SampleConfig.debug
// Config.Adhoc.xcconfig
PRODUCT_BUNDLE_IDENTIFIER=com.example.SampleConfig.adhoc
// Config.Store.xcconfig
PRODUCT_BUNDLE_IDENTIFIER=com.example.SampleConfig
PRODUCT_BUNDLE_IDENTIFIER
等の文字列の調べ方はのちに紹介します。
xcconfigファイルの指定と反映
projectファイルを指定して、Configurationsに1つAdhocという値を追加します。
Releaseの下にある+ボタンを押してDuplicate “Release” Configurationを押します。
名前はなんでも良いのですが、わかりやすい環境名にします。
今回はAdhocにしました。
そして以下のようにBased on Configuration Fileを指定します。
ここで1度ビルドしてください。(Cmd + B)
以下のようにTargetの左にConfig.Fileのカラムが追加されています。
これを値として使用するために、Targetの値を削除してください。
以下のようにフォーカスされている部分がConfig.Fileの列になっていれば大丈夫です。
次にSchemeで切り替えできるように設定していきます。
Schemeの生成
Manage Schemes… を選択してください。
設定されているScheme一覧が表示されます。
一覧の下にある+を押して、新しいSchemeを作成してください。
名前は適当に\(Target名)-\(環境名)
にしてみました。
Targetに関しては適切なものを指定してもらえれば問題ないです。
同様の作業で、Debug用のSchemeも作成します。
今回は以下のようにSchemeを作成しました。
環境の割り振り
- SampleConfig : 申請用 (Config.Store.xcconfigを割り当てる)
- SampleConfig-Adhoc : Adhoc用(Config.Adhoc.xcconfigを割り当てる)
- SampleConfig-Debug : Debug用(Config.Debug.xcconfigを割り当てる)
各SchemeにConfigを割り当てる
これで値を反映できるようになります。
試しにSampleConfig-AdhocにConfig.Adhoc.xcconfig
の値が反映されたbuildができるようします。
以下のようにSampleConfig-AdhocのSchemeを選択して、Edit Scheme…を押してください。
Run > Info > Build Configuration の値をDebugからAdhocに変えてください。
この状態でCloseを押して、ビルド(Cmd + B)してみます。
以下のようにBundle IdentifierがConfig.Adhoc.xcconfig
で指定した値になっていたら成功です。
(1度カラムを移動しないと表示の反映がされないっぽいので、気をつけてください。)
同じようにBuild Configrationの値をDebugやReleaseに差し替えると値が変わるようになります。
CocoaPodsを使っている場合の指定方法
CocoaPodsもConfigファイルを指定して、ビルド依存などを実現しています。
なのでProject > ConfigrationでConfigファイルを指定しているとエラーやワーニングが出てきます。
試しにこのプロジェクトでHimotokiをCocoaPodsで使用するようにPodfileを編集してインストールしてみました。
(Himotokiはとてもお世話になっていて、Swiftの書き方とかも学んでいるので使わせていただきました。)
以下は使用したPodfile
です。
# Podfile
# Uncomment the next line to define a global platform for your project
platform :ios, '8.0'
target 'SampleConfig' do
# Comment the next line if you're not using Swift and don't want to use dynamic frameworks
use_frameworks!
# Pods for SampleConfig
pod 'Himotoki'
end
以下がログです。
$ bundle exec pod install
Analyzing dependencies
Downloading dependencies
Installing Himotoki (3.0.1)
Generating Pods project
Integrating client project
[!] Please close any current Xcode sessions and use `SampleConfig.xcworkspace` for this project from now on.
Pod installation complete! There is 1 dependency from the Podfile and 1 total pod installed.
[!] CocoaPods did not set the base configuration of your project because your project already has a custom config set. In order for CocoaPods integration to work at all, please either set the base configurations of the target `SampleConfig` to `Pods/Target Support Files/Pods-SampleConfig/Pods-SampleConfig.debug.xcconfig` or include the `Pods/Target Support Files/Pods-SampleConfig/Pods-SampleConfig.debug.xcconfig` in your build configuration (`SampleConfig/Configs/Config.Debug.xcconfig`).
[!] CocoaPods did not set the base configuration of your project because your project already has a custom config set. In order for CocoaPods integration to work at all, please either set the base configurations of the target `SampleConfig` to `Pods/Target Support Files/Pods-SampleConfig/Pods-SampleConfig.release.xcconfig` or include the `Pods/Target Support Files/Pods-SampleConfig/Pods-SampleConfig.release.xcconfig` in your build configuration (`SampleConfig/Configs/Config.Store.xcconfig`).
[!] CocoaPods did not set the base configuration of your project because your project already has a custom config set. In order for CocoaPods integration to work at all, please either set the base configurations of the target `SampleConfig` to `Pods/Target Support Files/Pods-SampleConfig/Pods-SampleConfig.adhoc.xcconfig` or include the `Pods/Target Support Files/Pods-SampleConfig/Pods-SampleConfig.adhoc.xcconfig` in your build configuration (`SampleConfig/Configs/Config.Adhoc.xcconfig`).
1行抜粋して…
please either set the base configurations of the target `SampleConfig` to `Pods/Target Support Files/Pods-SampleConfig/Pods-SampleConfig.adhoc.xcconfig` or include the `Pods/Target Support Files/Pods-SampleConfig/Pods-SampleConfig.adhoc.xcconfig` in your build configuration (`SampleConfig/Configs/Config.Adhoc.xcconfig`).
とあるようにすでにConfigファイルが指定されているから、Pods/Target Support Files/Pods-SampleConfig/Pods-SampleConfig.adhoc.xcconfig
に変えるかinclude
してくれと表示されます。
のでinclude
します。
試しにConfig.Adhoc.xcconfig
でinclude
してみます。
#include "Pods/Target Support Files/Pods-SampleConfig/Pods-SampleConfig.adhoc.xcconfig"
PRODUCT_BUNDLE_IDENTIFIER=com.example.SampleConfig.adhoc
この状態でもう1度pod install
してみます。
$ bundle exec pod install
Analyzing dependencies
Downloading dependencies
Using Himotoki (3.0.1)
Generating Pods project
Integrating client project
Pod installation complete! There is 1 dependency from the Podfile and 1 total pod installed.
[!] CocoaPods did not set the base configuration of your project because your project already has a custom config set. In order for CocoaPods integration to work at all, please either set the base configurations of the target `SampleConfig` to `Pods/Target Support Files/Pods-SampleConfig/Pods-SampleConfig.debug.xcconfig` or include the `Pods/Target Support Files/Pods-SampleConfig/Pods-SampleConfig.debug.xcconfig` in your build configuration (`SampleConfig/Configs/Config.Debug.xcconfig`).
[!] CocoaPods did not set the base configuration of your project because your project already has a custom config set. In order for CocoaPods integration to work at all, please either set the base configurations of the target `SampleConfig` to `Pods/Target Support Files/Pods-SampleConfig/Pods-SampleConfig.release.xcconfig` or include the `Pods/Target Support Files/Pods-SampleConfig/Pods-SampleConfig.release.xcconfig` in your build configuration (`SampleConfig/Configs/Config.Store.xcconfig`).
上記のようにAdhocのワーニングが消えました。のでこれを全てに反映してみます。
// Config.Debug.xcconfig
#include "Pods/Target Support Files/Pods-SampleConfig/Pods-SampleConfig.debug.xcconfig"
PRODUCT_BUNDLE_IDENTIFIER=com.example.SampleConfig.debug
// Config.Store.xcconfig
#include "Pods/Target Support Files/Pods-SampleConfig/Pods-SampleConfig.release.xcconfig"
PRODUCT_BUNDLE_IDENTIFIER=com.example.SampleConfig
の状態で再度pod install
すると
$ bundle exec pod install
Analyzing dependencies
Downloading dependencies
Using Himotoki (3.0.1)
Generating Pods project
Integrating client project
Pod installation complete! There is 1 dependency from the Podfile and 1 total pod installed.
上記のようにワーニングが無くなります。
Configで操作したい値のKEYの見つけ方
Keyの見つけ方の紹介です。
Projectファイル > Targetの選択 > Build Settings と選択していき、反映させたい値を選択します。
すると右にあるwindowのDeclarationの横に書いてある値がKEYになります。
その下にあるValue Typeが指定できる値になります。
例えばOTHER_SWIFT_FLAGS
は以下のように指定できます。
// Config.Debug.xcconfig
OTHER_SWIFT_FLAGS = $(inherited) "-D" "DEBUG" "-D" "ADHOC"
$(inherited)
は前の状態を引き継ぐって意味があります。
最後に私がxcconfigを設定してからぶち当たった問題と解決方法の紹介をします。
Config周りで起こり得る問題点と解消方法
xcconfigで書いた値が反映されない
ダメな場合は1度プロジェクトをクリーン(Cmd + K)をしてください。
ビルド時に反映されますが、差分ビルドが走る時は値が反映されないことがありました。
Configファイルの値を変えるときはクリーンビルドすることをオススメします。
xcconfigで書いた値が反映されない(その2)
クリーンしてもだめな場合はそもそもBuild SettingsでTargetの値が優先されている場合があります。
Project
> Build Settins
で追加した値がしっかりフォーカスされているか確認してください。
これでうまく値が反映されない場合はそもそもKeyが違う可能性がありますので、xcconfig
ファイルをご確認ください。
終わりに
この記事のソースコードは以下のレポジトリにまとめました。
開発の環境構築はプロジェクトの開発スピードUpに直結するので、できる限り早く着手したいところです。
特に環境変数周りは手で操作しているとミスして、最悪審査通過後まで気がつかない不安があるので早めにBuildなどの処理時に変わるように修正することをお勧めします。
このように漫画PF事業部はプロジェクトのPDCAを早く回すために自動化処理や環境構築周りに全力で取り組んでおります。
iOSの開発環境構築や自動化処理などに興味がある方が現在苦労している人いましたらぜひお話出来ればと思います!