XcodeでProjectのTargets増やすのやめようよ。。。

今まで色々なプロジェクトに携わってきましたが、 Targetsによる管理が適切でないケースでTargetsを追加されると、保守が辛いなーと思ったのでシェア。

Targetsを増やすべきケース

そもそも、どういったケースでTargetsを増やすべきなのでしょうか。
Xcode Conceptsには、A target defines a single productとの記載があります。
つまり、以下のようなケースではTargetsによる管理が適切と考えられます。

  • 同じアプリの有料版と無料版を管理する場合
  • 基本的なロジックは同じだが、画像などの素材だけ差し替えて別アプリとしてリリースする場合

Targetsを増やすべきでないケース

では、逆にTargetsを増やすべきでないケースはどのようなものでしょうか。
開発版・ステージング版・リリース版をTargetsで管理しているケースをよく見ますが、これはTargetsで管理すべきではない例だと考えています。

なぜTargetsを増やすべきでないのか

では、なぜTargetsで管理すべきではないのでしょうか。
大きく2つの理由があります。

設定がDRYではなくなる

Targetsを増やすと、TargetsごとにInfo.plistが生成されます。
そのため、Crashlyticsの導入や、Background Modesを設定する場合には、Info.plistの数だけ設定をコピペしなければならず、DRYではなくなります。
また、コピペ作業を行うという自体、バグを生みかねません。

Targetごとにバグが再現する、しないなどが発生しやすくなる。

extensionのファイルで次のようなTarget設定が行われていた場合、
いずれの環境においてもビルドは通りますが、 AdHoc、Releaseビルドにおいてextensionに記載されたメソッドを呼びだそうとした場合、 unrecognized selector sent to instanceというランタイムエラーが発生します。 f:id:nerd0geek1:20160211161842p:plain

ではどうするべきか

このように、Targetsでビルドを管理する場合、バグが発生しやすくなります。 そのため、環境ごとのビルド管理には、Build SchemeとConfigurationによる管理のほうが適していると考えています。 f:id:nerd0geek1:20160211163019p:plain

環境ごとに変える必要がある内容は以下の項目から定義することができます。 Bundle Identifier : Targets > Build Settings > Packaging > Product Bundle Identifier Preprocessor Macro(Objective-Cの場合) : Targets > Build Settings > Apple LLVM 7.0 Preprocessing > Preprocessor Macros Preprocessor Macro(Swiftの場合) : Targets > Build Settings > Swift Compiler - Custom Flags > Other Swift Flags

まとめ

いかがでしたでしょうか。
Build SchemeとConfigurationによる管理は、Targetsによる管理よりもバグを起こしにくいので、導入してみてはいかがでしょうか。

参考