Objective-Cでは、マクロを使用してデバイスまたはシミュレーター向けにアプリが構築されているかどうかを確認できます。
#if TARGET_IPHONE_SIMULATOR
// Simulator
#else
// Device
#endif
これらはコンパイル時マクロであり、実行時には使用できません。
Swiftで同じことをするにはどうすればよいですか?
Objective-Cでは、マクロを使用してデバイスまたはシミュレーター向けにアプリが構築されているかどうかを確認できます。
#if TARGET_IPHONE_SIMULATOR
// Simulator
#else
// Device
#endif
これらはコンパイル時マクロであり、実行時には使用できません。
Swiftで同じことをするにはどうすればよいですか?
回答:
この答えはうまくいくかもしれませんが、静的チェックの推奨される解決策(いくつかのAppleエンジニアによって明らかにされています)は、iOSシミュレータをターゲットとするカスタムコンパイラフラグを定義することです。それを行う方法の詳細な手順については、@ mbelskyの回答を参照してください。
静的チェックが必要な場合(ランタイムのif / elseなどではない)、シミュレータを直接検出することはできませんが、次のようにデスクトップアーキテクチャでiOSを検出できます。
#if (arch(i386) || arch(x86_64)) && os(iOS)
...
#endif
Swift 4.1バージョン以降
すべてのタイプのシミュレーターが1つの条件のみを適用する必要があるため、最新の使用法がオールインワン条件に直接適用されます-
#if targetEnvironment(simulator)
// your simulator code
#else
// your real device code
#endif
詳細については、Swiftの提案SE-0190を確認してください。
古いバージョンの場合 -
明らかに、これはデバイスではfalseですが、ドキュメントで指定されているように、iOSシミュレーターではtrueを返します。
コードが32ビットiOSシミュレーター用にコンパイルされると、arch(i386)ビルド構成はtrueを返します。
iOS以外のシミュレータ用に開発している場合は、os
パラメータを変更するだけです。例:
watchOSシミュレーターを検出する
#if (arch(i386) || arch(x86_64)) && os(watchOS)
...
#endif
tvOSシミュレーターを検出する
#if (arch(i386) || arch(x86_64)) && os(tvOS)
...
#endif
または、でも、検出任意のシミュレータを
#if (arch(i386) || arch(x86_64)) && (os(iOS) || os(watchOS) || os(tvOS))
...
#endif
代わりにランタイムチェックで問題がなければ、TARGET_OS_SIMULATOR
変数(またはTARGET_IPHONE_SIMULATOR
iOS 8以下)を検査できます。これはシミュレーターで真実です。
これはプリプロセッサフラグを使用する場合とは異なり、多少制限があることに注意してください。たとえば、a if/else
が構文的に無効な場所(たとえば関数スコープの外)で使用することはできません。
たとえば、デバイスとシミュレータに異なるインポートを設定するとします。これは、動的チェックでは不可能ですが、静的チェックでは簡単です。
#if (arch(i386) || arch(x86_64)) && os(iOS)
import Foo
#else
import Bar
#endif
また、フラグはSwiftプリプロセッサによってa 0
またはaに置き換えられるため、式1
で直接使用するとif/else
、コンパイラは到達不能コードに関する警告を表示します。
この警告を回避するには、他の回答のいずれかを参照してください。
#if targetEnvironment(simulator)
:)(github.com/apple/swift-evolution/blob/master/proposals/...)
SWIFT 4.1より古い。#if targetEnvironment(simulator)
代わりに使用してください。ソース
Swiftでシミュレーターを検出するには、ビルド構成を使用できます。
これで、このステートメントを使用してシミュレーターを検出できます。
#if IOS_SIMULATOR
print("It's an iOS Simulator")
#else
print("It's a device")
#endif
また、UIDeviceクラスを拡張することもできます。
extension UIDevice {
var isSimulator: Bool {
#if IOS_SIMULATOR
return true
#else
return false
#endif
}
}
// Example of usage: UIDevice.current.isSimulator
xcconfig
使用してファイルOTHER_SWIFT_FLAGS = TARGET_OS_EMBEDDED
とOTHER_SWIFT_FLAGS[sdk=embeddedsimulator*] = TARGET_OS_SIMULATOR
シミュレータのために上書きします。
2018年2月20日現在の更新された情報
@russbishopには信頼できる回答があり、この回答が「正しくない」ように見えます-長期間動作しているように見えましたが。
Swiftでデバイスまたはシミュレーター用にアプリがビルドされているかどうかを検出する
前の回答
@WZWの回答と@Pangのコメントに基づいて、簡単なユーティリティ構造体を作成しました。このソリューションは、@ WZWの回答によって生成される警告を回避します。
import Foundation
struct Platform {
static var isSimulator: Bool {
return TARGET_OS_SIMULATOR != 0
}
}
使用例:
if Platform.isSimulator {
print("Running on Simulator")
}
public let IS_SIMULATOR = (TARGET_OS_SIMULATOR != 0)
。+1感謝
TARGET_OS_SIMULATOR != 0
はすでに回答に含まれています。それはダニエルによって与えられた解決策です。自由変数に再度追加する必要はありません。すでに存在しています。構造体でそれを使用するのが悪いと思い、自由変数で使用する方が良い場合は、これについてコメントを投稿するか、自分で答えてください。ありがとう。
Xcode 9.3以降
#if targetEnvironment(simulator)
Swiftは、単一の有効な引数シミュレータを備えた新しいプラットフォーム条件targetEnvironmentをサポートします。'#if targetEnvironment(simulator)'形式の条件付きコンパイルを使用して、ビルドターゲットがシミュレーターであることを検出できるようになりました。Swiftコンパイラーは、既存のos()およびarch()プラットフォーム条件を介して間接的にシミュレーター環境をテストしているように見えるプラットフォーム条件を評価するときに、targetEnvironment(simulator)の使用を検出、警告、および提案しようとします。(SE-0190)
iOS 9以降:
extension UIDevice {
static var isSimulator: Bool {
return NSProcessInfo.processInfo().environment["SIMULATOR_DEVICE_NAME"] != nil
}
}
スウィフト3:
extension UIDevice {
static var isSimulator: Bool {
return ProcessInfo.processInfo.environment["SIMULATOR_DEVICE_NAME"] != nil
}
}
iOS 9より前:
extension UIDevice {
static var isSimulator: Bool {
return UIDevice.currentDevice().model == "iPhone Simulator"
}
}
Objective-C:
@interface UIDevice (Additions)
- (BOOL)isSimulator;
@end
@implementation UIDevice (Additions)
- (BOOL)isSimulator {
if([[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){9, 0, 0}]) {
return [NSProcessInfo processInfo].environment[@"SIMULATOR_DEVICE_NAME"] != nil;
} else {
return [[self model] isEqualToString:@"iPhone Simulator"];
}
}
@end
will never be executed
警告を出さない
targetEnvironment(simulator)
これで引数として使用できます。
#if targetEnvironment(simulator)
// Simulator
#else
// Device
#endif
Xcode 9.3用に更新
ここでいくつかのことを明確にしましょう:
TARGET_OS_SIMULATOR
多くの場合、Swiftコードでは設定されません。ブリッジングヘッダーが原因で誤ってインポートされる可能性がありますが、これは脆弱であり、サポートされていません。また、フレームワークでは不可能です。これが、これがSwiftで機能するかどうか混乱している理由です。動的チェックを実行するには:
チェックProcessInfo.processInfo.environment["SIMULATOR_DEVICE_NAME"] != nil
は完全に問題ありません。
また、のSIMULATOR_MODEL_IDENTIFIER
ような文字列を返すかどうかを確認することで、シミュレーションされる基になるモデルを取得することもできますiPhone10,3
。
静的チェックを実行するには:
Xcode 9.2以前:独自のSwiftコンパイルフラグを定義します(他の回答に示されています)。
Xcode 9.3以降では、新しいtargetEnvironment条件を使用します。
#if targetEnvironment(simulator)
// for sim only
#else
// for device
#endif
targetEnvironment
はXcode 9.3に導入されました。新しいバージョンのXcodeが必要です。
ランタイムですが、ここにある他のほとんどのソリューションよりも単純です。
if TARGET_OS_SIMULATOR != 0 {
// target is current running in the simulator
}
または、プリプロセッサマクロを使用するブール値を返すObjective-Cヘルパー関数を呼び出すだけでもかまいません(特に、プロジェクトで既に混合している場合)。
編集:特にXcode 9.3の時点では、最善の解決策ではありません。HotJardの回答を見る
== 0
代わりに使用したときにのみ警告が表示されます!= 0
。上記のようにそれを使用したelse
後、ブロックを続けても、Swift 4 Xcodeバージョン9.2(9C40b)で警告は生成されません
TARGET_IPHONE_SIMULATOR
iOS 9では非推奨ですTARGET_OS_SIMULATOR
。代わりに またTARGET_OS_EMBEDDED
利用できます。
TargetConditionals.hから:
#if defined(__GNUC__) && ( defined(__APPLE_CPP__) || defined(__APPLE_CC__) || defined(__MACOS_CLASSIC__) ) . . . #define TARGET_OS_SIMULATOR 0 #define TARGET_OS_EMBEDDED 1 #define TARGET_IPHONE_SIMULATOR TARGET_OS_SIMULATOR /* deprecated */ #define TARGET_OS_NANO TARGET_OS_WATCH /* deprecated */
この拡張機能がお役に立てば幸いです。
extension UIDevice {
static var isSimulator: Bool = {
#if targetEnvironment(simulator)
return true
#else
return false
#endif
}()
}
使用法:
if UIDevice.isSimulator {
print("running on simulator")
}
Xcode 7.2(およびそれ以前のバージョンではテストしていません)では、「Any iOS Simulator」に対してプラットフォーム固有のビルドフラグ「-D TARGET_IPHONE_SIMULATOR」を設定できます。
「Swift Compiler-Customer Flags」のプロジェクトビルド設定を確認し、「Other Swift Flags」でフラグを設定します。ビルド構成にカーソルを合わせたときに「プラス」アイコンをクリックすると、プラットフォーム固有のフラグを設定できます。
このようにすることにはいくつかの利点があります。1)SwiftとObjective-Cのコードで同じ条件テスト( "#if TARGET_IPHONE_SIMULATOR")を使用できます。2)各ビルドにのみ適用される変数をコンパイルできます。
ここですべて説明Darwin.TargetConditionals:https : //github.com/apple/swift-corelibs-foundation/blob/master/CoreFoundation/Base.subproj/SwiftRuntime/TargetConditionals.h
TARGET_OS_SIMULATOR - Generated code will run under a simulator
私はSwift 3で以下のコードを使用しました
if TARGET_IPHONE_SIMULATOR == 1 {
//simulator
} else {
//device
}
現在、ProcessInfoクラスを使用して、デバイスがシミュレータであるかどうか、およびどの種類のデバイスが使用されているかを確認します。
if let simModelCode = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] {
print("yes is a simulator :\(simModelCode)")
}
しかし、ご存じのように、simModelCode
どの種類のシミュレーターが起動されたかをすぐに理解するのに適したコードではないので、必要に応じて、この別のSOの答えを見て、現在のiPhone /デバイスモデルを特定し、より人間的なものにすることができます。読み取り可能な文字列。
上記のHotJardの素晴らしい答えに基づいたXcode 11 Swiftの例を次に示します。これにより、isDevice
Boolが追加され、SIMULATOR_UDID
名前の代わりに使用されます。変数の割り当ては各行で行われるため、必要に応じてデバッガーで変数の割り当てを簡単に調べることができます。
import Foundation
// Extensions to UIDevice based on ProcessInfo.processInfo.environment keys
// to determine if the app is running on an actual device or the Simulator.
@objc extension UIDevice {
static var isSimulator: Bool {
let environment = ProcessInfo.processInfo.environment
let isSimulator = environment["SIMULATOR_UDID"] != nil
return isSimulator
}
static var isDevice: Bool {
let environment = ProcessInfo.processInfo.environment
let isDevice = environment["SIMULATOR_UDID"] == nil
return isDevice
}
}
DTPlatformName
を含む必要がある辞書エントリもありますsimulator
。
以下のコードを使用してください:
#if targetEnvironment(simulator)
// Simulator
#else
// Device
#endif
以下のための作品Swift 4
とXcode 9.4.1
Xcode 11、Swift 5
#if !targetEnvironment(macCatalyst)
#if targetEnvironment(simulator)
true
#else
false
#endif
#endif