回答:
はい、できます。
Swiftでは、Appleのドキュメントに従って、「#if /#else /#endif」プリプロセッサマクロを使用できます(ただし、より制約されます)。次に例を示します。
#if DEBUG
let a = 2
#else
let a = 3
#endif
ただし、「デバッグ」シンボルを他の場所に設定する必要があります。「Swift Compiler-Custom Flags」セクションの「Other Swift Flags」行で設定します。-D DEBUG
エントリと共にDEBUGシンボルを追加します。
通常どおり、デバッグ時またはリリース時に別の値を設定できます。
私はそれを実際のコードでテストしましたが、うまくいきました。遊び場では認識されていないようです。
重要な注意: -DDEBUG=1
機能しません。のみ-D DEBUG
機能します。コンパイラは特定の値のフラグを無視しているようです。
-D DEBUG
上記の追加に加えてDEBUG=1
、Apple LLVM 6.0 - Preprocessing
-> でも定義する必要がありますPreprocessor Macros
。
-DDEBUG
次の回答から変更するまで、私はこれを機能させることができませんでした:stackoverflow.com/a/24112024/747369。
DEBUG=1
する必要はありPreprocessor Macros
ません。
Apple Docsで述べたように
Swiftコンパイラにはプリプロセッサは含まれていません。代わりに、コンパイル時の属性、ビルド構成、および言語機能を利用して、同じ機能を実現します。このため、プリプロセッサディレクティブはSwiftにインポートされません。
カスタムビルド構成を使用して、私がやりたかったことを達成できました。
ターゲットを確認する方法は次のとおりです。
#if BANANA
print("We have a banana")
#elseif MELONA
print("Melona")
#else
print("Kiwi")
#endif
Swift 2.2を使用してテスト済み
-DLOCAL
、私には#if LOCAl #else #endif
、それがに該当する#else
セクション。元のターゲットを複製してAppTarget
名前を変更しAppTargetLocal
、カスタムフラグを設定しました。
#if LOCAL
ました。シミュレーターで実行したときに意図した結果であり、#else
テスト中に当てはまります。#if LOCAL
テスト中にも落ち込んで欲しいです。
多くの場合、条件付きコンパイルは実際には必要ありません。オンとオフを切り替えることができる条件付きの動作が必要なだけです。そのために、環境変数を使用できます。これには、実際に再コンパイルする必要がないという大きな利点があります。
スキームエディターで環境変数を設定し、簡単にオンまたはオフに切り替えることができます。
NSProcessInfoを使用して環境変数を取得できます。
let dic = NSProcessInfo.processInfo().environment
if dic["TRIPLE"] != nil {
// ... do secret stuff here ...
}
これが実際の例です。私のアプリはデバイス上でのみ実行されます。これは、シミュレータには存在しない音楽ライブラリを使用しているためです。では、私が所有していないデバイスのシミュレータでスクリーンショットを撮るにはどうすればよいですか?これらのスクリーンショットがないと、AppStoreに送信できません。
偽のデータとそれを処理する別の方法が必要です。私は2つの環境変数を使用しています。1つは、スイッチをオンにしたときに、デバイスで実行中に実際のデータから偽のデータを生成するようにアプリに指示します。もう1つは、スイッチをオンにすると、シミュレーターでの実行中に(欠落している音楽ライブラリではなく)偽のデータを使用します。Schemeエディターの環境変数のチェックボックスにより、これらの特別なモードのオン/オフを簡単に切り替えることができます。さらに、アーカイブには環境変数がないため、App Storeビルドで誤って使用することはできません。
ifdef
Xcode 8では、置換の大きな変更がありました。つまり、アクティブなコンパイル条件の使用です。
参照してくださいビルとリンクにXcodeの8リリースノート。
新しいビルド設定
新しい設定: SWIFT_ACTIVE_COMPILATION_CONDITIONS
“Active Compilation Conditions” is a new build setting for passing conditional compilation flags to the Swift compiler.
以前は、条件付きコンパイルフラグをOTHER_SWIFT_FLAGSで宣言し、設定の前に「-D」を付けることを忘れないでいました。たとえば、MYFLAG値を使用して条件付きでコンパイルするには:
#if MYFLAG1
// stuff 1
#elseif MYFLAG2
// stuff 2
#else
// stuff 3
#endif
設定に追加する値 -DMYFLAG
これで、値MYFLAGを新しい設定に渡すだけで済みます。これらすべての条件付きコンパイル値を移動する時間です!
Xcode 8のSwiftビルド設定機能の詳細については、以下のリンクを参照してください:http : //www.miqu.me/blog/2016/07/31/xcode-8-new-build-settings-and-analyzer-improvements/
Swift 4.1以降では、コードがデバッグまたはリリース構成でビルドされているかどうかを確認するだけの場合は、組み込み関数を使用できます。
_isDebugAssertConfiguration()
(最適化がに設定されている場合はtrue -Onone
)_isReleaseAssertConfiguration()
(最適化がに設定されている場合はtrue -O
)_isFastAssertConfiguration()
(最適化がに設定されている場合はtrue -Ounchecked
)例えば
func obtain() -> AbstractThing {
if _isDebugAssertConfiguration() {
return DecoratedThingWithDebugInformation(Thing())
} else {
return Thing()
}
}
プリプロセッサマクロと比較すると、
-D DEBUG
フラグを定義する必要はありません。✗ドキュメント化されていません。つまり、更新時に関数を削除できます(ただし、オプティマイザがこれらを定数に変換するため、AppStoreセーフである必要があります)。
@testable
属性の欠如のために公に持ち帰られましたが、将来のスウィフトについては運命は不明です。if if / elseで使用すると、常に「実行されない」という警告が生成されます。
if _isDebugAssertConfiguration()
で評価されif false
、if true
デバッグモードです。
ビルド設定/ Swiftコンパイラのカスタムフラグのアクティブコンパイル条件設定を使用します。
ALPHA
、BETA
など次に、次のようなコンパイル条件で確認します。
#if ALPHA
//
#elseif BETA
//
#else
//
#endif
ヒント:
#if !ALPHA
なども使用できます。
Swiftプリプロセッサはありません。(1つには、任意のコード置換により、タイプおよびメモリの安全性が損なわれます。)
ただし、Swiftにはビルド時の構成オプションが含まれているため、特定のプラットフォームまたはビルドスタイルのコードを条件付きで含めるか、-D
コンパイラー引数で定義したフラグに応じて含めることができます。ただし、Cとは異なり、コードの条件付きコンパイルセクションは構文的に完全でなければなりません。CocoaおよびObjective-CでのSwiftの使用に、これに関するセクションがあります。
例えば:
#if os(iOS)
let color = UIColor.redColor()
#else
let color = NSColor.redColor()
#endif
INT_CONST
場所float
ならどこにでも置くことができます。Swiftはこれを許可しません。また、var floatVal = INT_CONST
やむを得ず実行できる場合は、コンパイラーがを期待しているときに後でどこかでブレークダウンしInt
ますが、それをとして使用しますFloat
(タイプはfloatVal
として推論されますInt
)。10キャスト後、マクロを削除するためのよりクリーンなもの
#if
コードベース全体に条件文を付けずに関数に渡すことができるブール値をもたらす、もう1つの、おそらくより単純なソリューションDEBUG
は、プロジェクトビルドターゲットの1つとして定義しActive Compilation Conditions
、以下を含めます(私はグローバル定数として定義します)。
#if DEBUG
let isDebug = true
#else
let isDebug = false
#endif
このコンセプトは kennytmの答え基づいています
kennytmと比較する場合の主な利点は、これがプライベートな方法や文書化されていない方法に依存しないことです。
ではスウィフト4:
let isDebug: Bool = {
var isDebug = false
// function with a side effect and Bool return value that we can pass into assert()
func set(debug: Bool) -> Bool {
isDebug = debug
return isDebug
}
// assert:
// "Condition is only evaluated in playgrounds and -Onone builds."
// so isDebug is never changed to true in Release builds
assert(set(debug: true))
return isDebug
}()
プリプロセッサマクロとkennytmの答えと比較して、
-D DEBUG
フラグを✓ 文書化されています。これは、関数が通常のAPIリリース/非推奨パターンに従うことを意味します。
✓if / elseで使用しても、「実行されない」という警告は生成されません。
Xcodeバージョン9.4.1で作成されたSwiftプロジェクトでは、Swift 4.1
#if DEBUG
#endif
プリプロセッサマクロではDEBUG = 1がXcodeによってすでに設定されているため、デフォルトで機能します。
そのため、#if DEBUGを「そのまま」使用できます。
ちなみに、一般的な条件コンパイルブロックの使用方法は、Appleの書籍「The Swift Programming Language 4.1」(セクション「コンパイラ制御ステートメント」)に記述されており、コンパイルフラグの記述方法と、SwiftのCマクロに対応するものは、別のAppleの本 『ココアとObjective CでのSwiftの使用』(セクションプリプロセッサディレクティブ内)
今後Appleが彼らの本のより詳細な内容と索引を書いてくれることを願っています。
で設定DEBUG=1
した後GCC_PREPROCESSOR_DEFINITIONS
ビルド私はこの呼び出しを行うために関数を使用することを好みます:
func executeInProduction(_ block: () -> Void)
{
#if !DEBUG
block()
#endif
}
そして、デバッグビルドで省略したいブロックをこの関数で囲みます。
executeInProduction {
Fabric.with([Crashlytics.self]) // Compiler checks this line even in Debug
}
と比較した場合の利点:
#if !DEBUG
Fabric.with([Crashlytics.self]) // This is not checked, may not compile in non-Debug builds
#endif
コンパイラがコードの構文をチェックするので、その構文が正しくビルドされていると確信しています。
これは、デバッグコンパイルでのみ実行されるアサートに依存するジョンウィリスの回答に基づいています。
func Log(_ str: String) {
assert(DebugLog(str))
}
func DebugLog(_ str: String) -> Bool {
print(str)
return true
}
私の使用例は、印刷ステートメントのロギングです。iPhone Xのリリースバージョンのベンチマークは次のとおりです。
let iterations = 100_000_000
let time1 = CFAbsoluteTimeGetCurrent()
for i in 0 ..< iterations {
Log ("⧉ unarchiveArray:\(fileName) memoryTime:\(memoryTime) count:\(array.count)")
}
var time2 = CFAbsoluteTimeGetCurrent()
print ("Log: \(time2-time1)" )
プリント:
Log: 0.0
Swift 4では関数呼び出しが完全に排除されているようです。