質問が述べているように、私は主に私のコードがシミュレータで実行されているかどうかを知りたいだけでなく、実行中またはシミュレートされている特定のiPhoneバージョンを知ることに興味があります。
編集:Wordを「プログラムで」質問名に追加しました。私の質問のポイントは、実行しているバージョン/シミュレータに応じてコードを動的に含める/除外できるようにすることです。したがって、この情報を提供できるプリプロセッサディレクティブのようなものを本当に探しています。
すでに尋ねましたが、非常に異なるタイトルで。
iPhone用にコンパイルするときにXcodeによって設定される#defines
そこから私の答えを繰り返します。
SDKドキュメントの「条件付きソースコードのコンパイル」にあります。
関連する定義はTARGET_OS_SIMULATORで、iOSフレームワーク内の/usr/include/TargetConditionals.hで定義されています。ツールチェーンの以前のバージョンでは、次のように書く必要がありました。
#include "TargetConditionals.h"
ただし、現在の(Xcode 6/iOS8)ツールチェーンではこれは不要です。
したがって、たとえば、デバイスで実行されていることを確認したい場合は、
#if TARGET_OS_SIMULATOR
// Simulator-specific code
#else
// Device-specific code
#endif
どちらがユースケースに適しているかによって異なります。
これは公式に機能するとされています。
#if TARGET_IPHONE_SIMULATOR
NSString *hello = @"Hello, iPhone simulator!";
#Elif TARGET_OS_IPHONE
NSString *hello = @"Hello, device!";
#else
NSString *hello = @"Hello, unknown target!";
#endif
このコードは、シミュレータで実行されているかどうかを示します。
#ifdef __i386__
NSLog(@"Running in the simulator");
#else
NSLog(@"Running on a device");
#endif
プリプロセッサディレクティブではありませんが、これは私がこの質問に来たときに探していたものです。
NSString *model = [[UIDevice currentDevice] model];
if ([model isEqualToString:@"iPhone Simulator"]) {
//device is simulator
}
これを行う最良の方法は次のとおりです。
#if TARGET_IPHONE_SIMULATOR
ではなく
#ifdef TARGET_IPHONE_SIMULATOR
常に定義されているため:0または1
Swiftの場合、以下を実装できます
構造化データを作成できる構造体を作成できます
struct Platform {
static let isSimulator: Bool = {
#if Arch(i386) || Arch(x86_64)
return true
#endif
return false
}()
}
その後、アプリがSwift thenのデバイスまたはシミュレータ用にビルドされているかどうかを検出したい場合。
if Platform.isSimulator {
// Do one thing
}
else {
// Do the other
}
ISより良い方法があります!
Xcode 9.3 beta 4では、#if targetEnvironment(simulator)
を使用して確認できます。
#if targetEnvironment(simulator)
//Your simulator code
#endif
UPDATE
Xcode 10およびiOS 12 SDKもこれをサポートしています。
これらの答えはすべて良いですが、コンパイルチェックとランタイムチェックを明確にしないため、私のような初心者を混乱させます。プリプロセッサはコンパイル前にありますが、より明確にする必要があります
このブログ記事では iPhoneシミュレーターの検出方法 を明確に示しています
ランタイム
まず、簡単に説明しましょう。 UIDeviceは、デバイスに関する情報を既に提供します
[[UIDevice currentDevice] model]
アプリの実行場所に応じて、「iPhone Simulator」または「iPhone」が返されます。
コンパイル時間
ただし、コンパイル時の定義を使用することです。どうして?シミュレータ内またはデバイス上で実行されるようにアプリを厳密にコンパイルするためです。 Appleは、TARGET_IPHONE_SIMULATOR
という名前の定義を作成します。それでは、コードを見てみましょう:
#if TARGET_IPHONE_SIMULATOR
NSLog(@"Running in Simulator - no app store or giro");
#endif
以前の回答は少し古くなっています。 TARGET_IPHONE_SIMULATOR
マクロを照会するだけでよいことがわかりました(他のヘッダーファイルを含める必要はありません [iOS用にコーディングしている場合])。
TARGET_OS_IPHONE
を試しましたが、実際のデバイスとシミュレーターで実行すると同じ値(1)を返しました。そのため、代わりにTARGET_IPHONE_SIMULATOR
を使用することをお勧めします。
Swift 4
およびXcode 9.4.1
に対応
このコードを使用してください:
#if targetEnvironment(simulator)
// Simulator
#else
// Device
#endif
私は同じ問題を抱えていました。TARGET_IPHONE_SIMULATOR
とTARGET_OS_IPHONE
の両方が常に定義され、1に設定されています。もちろん、ピートのソリューションは動作しますが、 iPhoneのハードウェアが変更されない限り安全です(したがって、コードは常にそこにあるiPhoneで常に機能します)。
#if defined __arm__ || defined __thumb__
#undef TARGET_IPHONE_SIMULATOR
#define TARGET_OS_IPHONE
#else
#define TARGET_IPHONE_SIMULATOR 1
#undef TARGET_OS_IPHONE
#endif
それをどこか便利な場所に置き、TARGET_*
定数が正しく定義されているふりをしてください。
For Swift 4.2/xCode 1
UIDeviceに拡張機能を作成したので、シミュレーターが実行されているかどうかを簡単に確認できます。
// UIDevice+CheckSimulator.Swift
import UIKit
extension UIDevice {
/// Checks if the current device that runs the app is xCode's simulator
static func isSimulator() -> Bool {
#if targetEnvironment(simulator)
return true
#else
return false
#endif
}
}
AppDelegateでは、このメソッドを使用して、リモート通知の登録が必要かどうかを判断しますが、これはシミュレータでは不可能です。
// CHECK FOR REAL DEVICE / OR SIMULATOR
if UIDevice.isSimulator() == false {
// REGISTER FOR SILENT REMOTE NOTIFICATION
application.registerForRemoteNotifications()
}
誰もが提供された答えを考えましたか ここ ?
Objective-Cの同等物は次のようになります
+ (BOOL)isSimulator {
NSOperatingSystemVersion ios9 = {9, 0, 0};
NSProcessInfo *processInfo = [NSProcessInfo processInfo];
if ([processInfo isOperatingSystemAtLeastVersion:ios9]) {
NSDictionary<NSString *, NSString *> *environment = [processInfo environment];
NSString *simulator = [environment objectForKey:@"SIMULATOR_DEVICE_NAME"];
return simulator != nil;
} else {
UIDevice *currentDevice = [UIDevice currentDevice];
return ([currentDevice.model rangeOfString:@"Simulator"].location != NSNotFound);
}
}
すべてのタイプの「シミュレータ」を含めるには
NSString *model = [[UIDevice currentDevice] model];
if([model rangeOfString:@"Simulator" options:NSCaseInsensitiveSearch].location !=NSNotFound)
{
// we are running in a simulator
}
Swift 4.2(Xcode 10)では、これを行うことができます
#if targetEnvironment(simulator)
//simulator code
#else
#warning("Not compiling for simulator")
#endif
///シミュレーターでデバイスではない場合にtrueを返します
public static var isSimulator: Bool {
#if (Arch(i386) || Arch(x86_64)) && os(iOS)
return true
#else
return false
#endif
}
何も機能しない場合は、これを試してください
public struct Platform {
public static var isSimulator: Bool {
return TARGET_OS_SIMULATOR != 0 // Use this line in Xcode 7 or newer
}
}
Appleは、アプリがシミュレーターをターゲットにしていることを確認するためのサポートを次のように追加しました。
#if targetEnvironment(simulator)
let DEVICE_IS_SIMULATOR = true
#else
let DEVICE_IS_SIMULATOR = false
#endif
私の答えは、@ Daniel Magnussonの回答と@Nuthatchと@ n.Drakeのコメントに基づいています。 iOS9以降で作業しているSwiftユーザーの時間を節約するために書きました。
これは私のために働いたものです:
if UIDevice.currentDevice().name.hasSuffix("Simulator"){
//Code executing on Simulator
} else{
//Code executing on Device
}
Swift 4ソリューション
static let isSimulator: Bool = {
return TARGET_OS_SIMULATOR == 1
}()
TARGET_OS_SIMULATOR
はDarwin.TargetConditionals.Swift
ファイルにあります。