経緯
あるライブラリが、シミュレータでのビルドに対応していなかった。しかしシミュレータでビルドして確かめたい点などもあるため、ターゲットを複数作り、一つはそのライブラリ有り、もう一つはライブラリ無しという形にする事にした。
やり方
Targetのコピー
- Xcode上で「プロジェクト名.xcodeproj」ファイル(青いやつ)をクリック -> Target よりコピーしたいTarget(ここでは
myProject
とする)を右クリックし、「Duplicate」を選択。「myProject copy」というTargetができる。クリックして、任意の名前に変える(ここでは、myProjectWithLibrary
とする)。- 完全に同じ設定のtargetがコピーされている。
-
The selected target is an iPhone target. Would you like to duplicate the iPhone target and transition the new target for running on iPad?
というダイアログが出てくる。意味的には、「コピー元はiPhoneがターゲットだけど、コピー先はiPad用にする?」と聞いてきている。特にそんなつもりはないため、「Duplicate only」を選択する。
Schemeの編集
- Schemeを編集する。Targetをコピーしたのに伴って、Schemeも自動で新設されている(Xcode左上より確認できる)。ただ名前は「myProject copy」のままなので、Schemeの名前も
myProjectWithLibrary
に直しておく。
Info.plist
- TargetのコピーによりInfo.plistもコピーされている。ただ、修正し忘れなどの観点から、特に事情がなければInfo.plistは同じものを一つだけ参照した方がいいと思われる。
- まず、自動生成された
myProject copy-Info.plist
を削除する。 - Targets > Build Settings > Packaging > Info.plist fileより、
myProject copy-Info.plist
を削除し、コピー元のInfo.plistのファイル名を入力する。
- まず、自動生成された
Target Membership
- Target Membershipの調整
- 今回入れたライブラリをインポートしているファイルがTarget Membershipに入っていると、シミュレータでビルドできなくなる状況であった。そのため、それらのファイルの
Target Membership
でmyProject
を外した。 - Xcodeの左メニューから各ファイルを選択し、右メニューのFile Inspector > Target Membershipより、どのTargetに追加するかチェックボックスで選ぶことができる。
- 以降、新規ファイルを追加する際は、
myProject
とmyProjectWithLibrary
の両方にチェックボックスが入っていることを確認する。 - マージなので、他の人が追加したファイルが流れてきた場合、
myProjectWithLibrary
にTarget Membershipがついていなかったりしたので、つけた上で、今後はつけてもらうよう周知した。
- 今回入れたライブラリをインポートしているファイルがTarget Membershipに入っていると、シミュレータでビルドできなくなる状況であった。そのため、それらのファイルの
プリプロセッサマクロ
- プリプロセッサマクロ
- 上記Target Membershipで、ファイル毎にどのTargetで使うか決められるわけだが、それだけでは足りない場合がある。ファイル内のあるコード(例えば、今回のライブラリをインポートする部分など) を、
myProjectWithLibrary
の時は実行したいがmyProject
の時は実行したくなかった。そのため、プリプロセッサマクロの設定をした。 - Targets >
myProjectWithLibrary
> Build Settings > Swift Compiler - Custom Flags > Other Swift Flags に、元々CocoaPodsの-D COCOAPODS
が入っていたが、-D WITHLIBRARY
というものを追加した。 - マクロの使用例は以下のようになる。
- 上記Target Membershipで、ファイル毎にどのTargetで使うか決められるわけだが、それだけでは足りない場合がある。ファイル内のあるコード(例えば、今回のライブラリをインポートする部分など) を、
AppDelegate.swift
#if WITHLIBRARY
import library
#endif
MainWireframe.swift
func presentXXXScene() {
#if DEBUG && WITHLIBRARY
let vc = XXXBuilder().build()
viewController.pushViewController(vc)
#endif
}
Podfile
- Targetが増えているので、Target事にライブラリを管理しているPodfileも直さなくてはいけない。
- 基本的には、
myProject
とmyProjectWithLibrary
で、CocoaPodで導入しているライブラリは全て同じであった。そのため、Podfile内で関数を定義するか、CocoaPodsのabstract target機能を用いて、同じ箇所に書いたライブラリ定義を二つのTargetで使いわ回すと良い。 - 参考 CocoaPods: The Elegant Solution To Installing The Same Pod In Multiple Targets、 stack overflow - How do I specify multiple targets in my podfile for my Xcode project?、What's a pod file?
- 基本的には、