質問が述べるように、私はコードがシミュレーターで実行されているかどうかを主に知りたいですが、実行中またはシミュレートされている特定のiphoneバージョンを知ることにも興味があります。
編集:質問名に「プログラムで」という単語を追加しました。私の質問のポイントは、実行されているバージョン/シミュレーターに応じてコードを動的に含めたり除外したりできるようにすることです。そのため、この情報を提供できるプリプロセッサーディレクティブのようなものを本当に探しています。
質問が述べるように、私はコードがシミュレーターで実行されているかどうかを主に知りたいですが、実行中またはシミュレートされている特定のiphoneバージョンを知ることにも興味があります。
編集:質問名に「プログラムで」という単語を追加しました。私の質問のポイントは、実行されているバージョン/シミュレーターに応じてコードを動的に含めたり除外したりできるようにすることです。そのため、この情報を提供できるプリプロセッサーディレクティブのようなものを本当に探しています。
回答:
すでに尋ねましたが、非常に異なるタイトルです。
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
}
[model compare:iPhoneSimulator] == NSOrderedSame
以下のように記述しなければならない[model isEqualToString:iPhoneSimulator]
[model hasSuffix:@"Simulator"]
、一般的に「シミュレータ」だけに関心があり、特にiPhoneやiPadには関心がない場合。この答えはiPadシミュレータでは機能しません:)
name
代わりにデバイスをチェックしてくださいmodel
Simulator
デバイス名に単語を追加した場合、コードは機能しません
今より良い方法があります!
Xcode 9.3ベータ4以降では#if targetEnvironment(simulator)
、チェックに使用できます。
#if targetEnvironment(simulator)
//Your simulator code
#endif
UPDATE
Xcode 10およびiOS 12 SDKもこれをサポートしています。
Swiftの場合、以下を実装できます
構造化データを作成できる構造体を作成できます
struct Platform {
static var isSimulator: Bool {
#if targetEnvironment(simulator)
// We're on the simulator
return true
#else
// We're on a device
return false
#endif
}
}
次に、アプリがSwiftのデバイスまたはシミュレーター用にビルドされているかどうかを検出したい場合。
if Platform.isSimulator {
// Do one thing
} else {
// Do the other
}
#if #else #endif
は良くなると思います。
以下のための作品Swift 5
とXcode 11.3.1
このコードを使用してください:
#if targetEnvironment(simulator)
// Simulator
#else
// Device
#endif
これらの答えはすべて良いですが、コンパイルチェックとランタイムチェックを明確にしないため、私のような初心者を混乱させます。プリプロセッサはコンパイル時より前ですが、より明確にする必要があります
このブログ記事は、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
[[UIDevice currentDevice] model]
がのiPhone
代わりに戻ってきiPhone Simulator
ます。したがって、これは最善のアプローチではないと思います。
以前の回答は少し古くなっています。私はあなたがする必要があるのはTARGET_IPHONE_SIMULATOR
マクロをクエリすることだけであることがわかりました(他のヘッダーファイルを含める必要はありません(iOS向けにコーディングしている場合))。
試してみましたTARGET_OS_IPHONE
が、実際のデバイスとシミュレーターで実行すると同じ値(1)が返されたため、TARGET_IPHONE_SIMULATOR
代わりに使用することをお勧めします。
私は同じ問題を抱えていた、両方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_*
定数が正しく定義されたとしましょう。
私は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);
}
}
Swift 4.2 / xCode 10の場合
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()
}
すべてのタイプの「シミュレータ」を含めるには
NSString *model = [[UIDevice currentDevice] model];
if([model rangeOfString:@"Simulator" options:NSCaseInsensitiveSearch].location !=NSNotFound)
{
// we are running in a simulator
}
-[NSString containsString]
?
私の回答は、@ Daniel Magnussonの回答と、@ Nuthatchと@ n.Drakeのコメントに基づいています。そして私はそれを書いて、iOS9以降で作業する迅速なユーザーのために時間を節約します。
これは私のために働いたものです:
if UIDevice.currentDevice().name.hasSuffix("Simulator"){
//Code executing on Simulator
} else{
//Code executing on Device
}
Simulator
デバイス名に単語を追加した場合、コードは機能しません
UIDevice.current.name
では、シミュレーターが実行されているマシンの名前(通常は「SimonのMacBook Pro」など)が報告されるため、テストの信頼性が低下しました。私はまだそれを修正するためのきれいな方法を探しています。
///デバイスではなくシミュレータの場合は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
}
}
私の意見では、答え(上に提示され、以下に繰り返されます):
NSString *model = [[UIDevice currentDevice] model];
if ([model isEqualToString:@"iPhone Simulator"]) {
//device is simulator
}
これは、コンパイル時ではなく実行時に実行されるため、最良の答えです。