Swift 条件付きコンパイル ステートメントで iOS 展開ターゲットを確認するにはどうすればよいですか?
私は次のことを試しました:
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0
// some code here
#else
// other code here
#endif
ただし、最初の式ではコンパイル エラーが発生します。
Expected '&&' or '||' expression
Swift 条件付きコンパイル ステートメントで iOS 展開ターゲットを確認するにはどうすればよいですか?
私は次のことを試しました:
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0
// some code here
#else
// other code here
#endif
ただし、最初の式ではコンパイル エラーが発生します。
Expected '&&' or '||' expression
TL;DR? > 3. 解決策へ
前処理ディレクティブに関するAppleのドキュメントによると:
Swift コンパイラにはプリプロセッサが含まれていません。代わりに、コンパイル時の属性、ビルド構成、および言語機能を利用して、同じ機能を実現します。このため、プリプロセッサ ディレクティブは Swift にインポートされません。
__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0
そのため、C のプリプロセス ディレクティブを使用しようとするとエラーが発生します。swift では#if
、 などの演算子では使用できません<
。あなたができることは次のとおりです。
#if [build configuration]
または条件付き:
#if [build configuration] && ![build configuration]
再び同じドキュメントから:
ビルド構成には、次の表に示すリテラルの true 値と false 値、コマンド ライン フラグ、およびプラットフォーム テスト関数が含まれます。-D <#flag#> を使用して、コマンド ライン フラグを指定できます。
true
andfalse
: 役に立たないos(iOS)
またはarch(arm64)
> は役に立たず、少し検索しましたが、それらがどこに定義されているかわかりません。(おそらくコンパイラ自体で?)少し回避策のように感じますが、仕事はします:
たとえば、もちろんターゲットが iOS7 であると仮定して、#if iOSVersionMinRequired7
代わりに を使用できます。__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_7_0
これは基本的に、プロジェクトで iOS 展開ターゲットのバージョンを変更することと同じですが、便利ではありません... もちろん、iOS バージョンのターゲットに応じて、関連するスキームを使用して複数のビルド構成を行うことができます。
Appleはきっとこれを改善するでしょう、おそらくいくつかの組み込み機能でos()
...
Swift 2.2 でテスト済み
つまり、またはDeployment Target
? 以下に、複数のバージョンのアプリ (無料アプリ、有料アプリなど) があり、異なるアプリ ターゲットを使用する場合のソリューションを提供します。iOS version
App Target
カスタム ビルド構成を設定できます:
1. プロジェクトに移動 / ターゲットを選択 / ビルド設定 / カスタム フラグを検索
2. 選択したターゲットに対して、Debug と Release
3-D
の両方でプレフィックス (空白なし)を使用してカスタム フラグを設定
あなたが持っているすべてのターゲットに対して上記の手順を実行します
ターゲットを区別するには、次のようにします。
var target: String {
var _target = ""
#if BANANA
_target = "Banana"
#elseif MELONA
_target = "Melona"
#else
_target = "Kiwi"
#endif
return _target
}
override func viewDidLoad() {
super.viewDidLoad()
print("Hello, this is target: \(target)"
}
そのような条件付きコンパイル ステートメントでは実行できません。Apple が呼ぶ「複雑なマクロ」は、Swift ではサポートされていません。ジェネリックと型は、頭の中で同じことを行い、より良い結果をもたらします。(これは彼らが公開したリンクです https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithCAPIs.html#//apple_ref/doc/uid/TP40014216-CH8-XID_13)
これは私が思いついた関数で、同じことを実現します(明らかに、文字列の戻り値を、ブール値やオプション自体のような便利なものに置き換えるだけです):
func checkVersion(ref : String) -> String {
let sys = UIDevice.currentDevice().systemVersion
switch sys.compare(ref, options: NSStringCompareOptions.NumericSearch, range: nil, locale: nil) {
case .OrderedAscending:
return ("\(ref) is greater than \(sys)")
case .OrderedDescending:
return ("\(ref) is less than \(sys)")
case .OrderedSame:
return ("\(ref) is the same as \(sys)")
}
}
// Usage
checkVersion("7.0") // Gives "7.0 is less than 8.0"
checkVersion("8.0") // Gives "8.0 is the same as 8.0"
checkVersion("8.2.5") // Gives "8.2.5 is greater than 8.0"
ソース コードが異なる機能を持つ複数の iOS および macOS バージョンをサポートするライブラリを構築するときに、最近、この問題に遭遇しました。
私の解決策は、実際の展開ターゲットから値を導出する Xcode でカスタム ビルド フラグを使用することです。
TARGET_IOS_MAJOR = TARGET_IOS_MAJOR_$(IPHONEOS_DEPLOYMENT_TARGET:base)
TARGET_MACOS_MAJOR = TARGET_MACOS_MAJOR_$(MACOSX_DEPLOYMENT_TARGET:base)
Others Swift Flagsでユーザー定義の設定を参照すると、次のようになります。
OTHER_SWIFT_FLAGS = -D$(TARGET_MACOS_MAJOR) -D$(TARGET_IOS_MAJOR)
次のように、Swift ソースで実際のメジャー OS バージョンを確認できます。
#if os(macOS)
#if TARGET_MACOS_MAJOR_12
#warning("TARGET_MACOS_MAJOR_12")
#elseif TARGET_MACOS_MAJOR_11
// use custom implementation
#warning("TARGET_MACOS_MAJOR_11")
#endif
#elseif os(iOS)
#if TARGET_IOS_MAJOR_15
#warning("TARGET_IOS_MAJOR_15")
#elseif TARGET_IOS_MAJOR_14
#warning("TARGET_IOS_MAJOR_14")
#else
#warning("older iOS")
#endif
#endif
現在、SPM パッケージで同様のアプローチが可能かどうかはわかりません。これは、後の段階でやろうとしていることです。