LoginSignup
9

More than 5 years have passed since last update.

複数Targetを単一ファイルで対応する (Xcode)

Last updated at Posted at 2019-02-13

Apple Watch 対応アプリなどを作成していると、複数 Target でほとんど同じコードを使用したいことが出てくると思います。例えば Object の定義ファイルなど。
ただその中でも1行だけ Target ごとで分岐したい箇所があったりすると思います。そのようなときの分岐方法をまとめました。

環境

  • Xcode 10.1

Conditional Compilation Block について

下記みたいなやつです。

#if [条件式]
[処理]
#endif

使えるのは、 #if #elseif #else #endif で、条件式で用いれるのは && || ! です。

全て混ぜたグチャグチャな例
#if !os(watchOS)
print("osがwatchOSではない")
#elseif arch(i386) || arch(x86_64)
print("CPUがi386かx86_64")
#else
print("osがwatchOS、もしくはCPUがi386かx86_64以外")
#endif

条件式で使える値は以降で説明します。

OS ごとの分岐

#if os(watchOS)

使える値は os(iOS) os(watchOS) os(macOS) os(tvOS) os(Linux) です。

その他の分岐 (Swiftバージョン等)

シミュレータか実機かの判定。

Simulator
#if targetEnvironment(simulator)

swift() で括弧内は >=数字 <数字 が使用できます。

Swiftバージョン
#if swift(>=4.2)

他の条件や詳しくは docs.swift.org Conditional Compilation Block にて。
arch()canImport() などあります。

Target や Configuration で分岐

Active Compilation Conditions に独自の値を設定することで、

下記のようにすることができます。
(おそらくDEBUGはデフォルトでセットされてると思います。)

#if DEBUG

Target ごとに設定したり Configuration ごとに設定することで、自由に分岐できます。

$(inherited) を活用

例えば複数 Target があり、全ての Configuration DebugActive Compilation Conditions に対して DEBUG をセットしたい場合。
それぞれの Target ページで設定してもいいのですが、一括でセットしたい。

このようなとき、値がより優先される Project の方に値を記述し、各 Target の方には $(inherited) と記入することで、Project の値が利用されます。

値の優先順位と $(inherited) について詳しくは こちらのQiita記事 を参照ください。

Xcode 7 以前でやっていたこと

Active Compilation Conditions は Xcode 8 から登場しました。
以前は Preprocessor MacrosOther Swift Flags をいじることにより実現していました。

以前の方法を使用するメリットはないと思いますが、念の為手段の一つとしてご紹介しました。

参考

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9