アプリがiPhoneシミュレーターで実行されているかどうかをプログラムで確認するにはどうすればよいですか?


270

質問が述べるように、私はコードがシミュレーターで実行されているかどうかを主に知りたいですが、実行中またはシミュレートされている特定のiphoneバージョンを知ることにも興味があります。

編集:質問名に「プログラムで」という単語を追加しました。私の質問のポイントは、実行されているバージョン/シミュレーターに応じてコードを動的に含めたり除外したりできるようにすることです。そのため、この情報を提供できるプリプロセッサーディレクティブのようなものを本当に探しています。


プリプロセッサディレクティブが動的であるかどうかはわかりません(とにかく探していたものかもしれませんが)。ディレクティブは、ビルドしたときに、どこで実行されるかを実際に知っていたことを意味します。
WiseOldDuck

回答:


356

すでに尋ねましたが、非常に異なるタイトルです。

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

どちらがあなたのユースケースに適しているかに依存します。


1
ありがとう。これは元の質問のより具体的なバージョンであることに同意します。もしあなたが私の最初の検索で出てきたなら、私は尋ねる必要さえなかったでしょう。
ジェフリーマイヤー

5
これらの定義に注意してください。メニュー項目「プロジェクト>アクティブSDKの設定>シミュレータ…」でコードをコンパイルすると、TARGET_OS_IPHONE変数が両方定義されているため、TARGET_IPHONE_SIMULATORになります。したがって、ロジックを分離する唯一の正しい方法は、Pete(Thanks dude)によって以下に指摘されています。
Vadim、

5
#ifと#ifdefの違いに注意してください。私にとってそれは不正確な振る舞いの原因でした。
Anton

7
おそらく、これが書かれてからTargetConditionalsを含める必要性はなくなりましたが、#if TARGET_IPHONE_SIMULATORがTargetConditionals.hを含めなくても機能することに注意してください。
dmur 14年

1
@Dimitrisそれは良い習慣です。あなたはTARGET_OS_SIMULATORがそのように、定義されている方法がわからない(TARGET_OS_SIMULATOR)TARGET_OS_SIMULATORと同一ではないかもしれない!!
Airsource株式会社

106

更新されたコード:

これは公式に機能するとされています。

#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

7
iOS 8およびXcode 6.1.1以降、TARGET_OS_IPHONEはシミュレーターでtrueです。
マルハル2015年

3
これは新しいXCodeバージョンではもう動作しません
Fabio Napodano

1
2016年に64ビットシミュレータを実行している場合を除きます。または2019年に、Intelプロセッサを搭載したiPhoneでコードを実行します。
gnasher729 2016

61

プリプロセッサディレクティブではありませんが、これは私がこの質問にたどり着いたときに探していたものです。

NSString *model = [[UIDevice currentDevice] model];
if ([model isEqualToString:@"iPhone Simulator"]) {
    //device is simulator
}

9
[model compare:iPhoneSimulator] == NSOrderedSame以下のように記述しなければならない[model isEqualToString:iPhoneSimulator]
user102008

18
あるいは[model hasSuffix:@"Simulator"]、一般的に「シミュレータ」だけに関心があり、特にiPhoneiPadに関心がない場合。この答えはiPadシミュレータでは機能しません:)
Nuthatch

Nuthatchのコメントがこれをtotoの最良の答えにしているため、賛成です。
Le Motは、2015

12
iOS9では、name代わりにデバイスをチェックしてくださいmodel
n.Drake

1
ユーザーがSimulatorデバイス名に単語を追加した場合、コードは機能しません
mbelsky

55

これを行う最良の方法は次のとおりです。

#if TARGET_IPHONE_SIMULATOR

ではなく

#ifdef TARGET_IPHONE_SIMULATOR

常に定義されているため:0または1


39

今より良い方法があります!

Xcode 9.3ベータ4以降では#if targetEnvironment(simulator)、チェックに使用できます。

#if targetEnvironment(simulator)
//Your simulator code
#endif

UPDATE
Xcode 10およびiOS 12 SDKもこれをサポートしています。


1
これが私に有効な唯一の方法であり、残りの解決策は機能しませんでした。
Vrutin Rathod

注これは迅速にのみ行われます。
マットS.

35

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
}

私の考えでは最もクリーンな実装であり、x86_64およびi386アーキテクチャを考慮しています。Core Dataの奇妙なデバイスとシミュレーターのバグを克服するのに役立ちました。あなたは男です!
Iron John Bonney

5
Playgroundでは、「 'return'の後のコードは実行されません」という警告が表示されます。だから私#if #else #endifは良くなると思います。
DawnSong

12

以下のための作品Swift 5Xcode 11.3.1

このコードを使用してください:

#if targetEnvironment(simulator)
   // Simulator
#else
   // Device
#endif

9

これらの答えはすべて良いですが、コンパイルチェックとランタイムチェックを明確にしないため、私のような初心者を混乱させます。プリプロセッサはコンパイル時より前ですが、より明確にする必要があります

このブログ記事は、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

1
これは他の答えをどのように改善しますか?
mmmmmm 2014年

@Mark Itは少し明確になります
onmyway133

5
現在、Xcode 7では、iOS 9シミュレーター[[UIDevice currentDevice] model]がのiPhone代わりに戻ってきiPhone Simulatorます。したがって、これは最善のアプローチではないと思います。
eMdOS 2016年

6

以前の回答は少し古くなっています。私はあなたがする必要があるのはTARGET_IPHONE_SIMULATORマクロをクエリすることだけであることがわかりました(他のヘッダーファイルを含める必要はありません(iOS向けにコーディングしている場合))。

試してみましたTARGET_OS_IPHONEが、実際のデバイスとシミュレーターで実行すると同じ値(1)が返されたため、TARGET_IPHONE_SIMULATOR代わりに使用することをお勧めします。


TARGET_OS_IPHONEは、iOSまたはMacOS Xで実行される可能性のあるコード用です。明らかに、そのコードをシミュレーターで「iPhone」のように動作させる必要があります。
gnasher729 2016

6

Macアプリを区別するには:#if(arch(i386)|| arch(x86_64))&&!os(OSX)// Macアプリではなく、Mac上で実行されているシミュレータを使用しています。(Macターゲットに含まれているクロスプラットフォームコードの場合)
Bobjt

4

私は同じ問題を抱えていた、両方TARGET_IPHONE_SIMULATORTARGET_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_*定数が正しく定義されたとしましょう。


4

誰かがここで提供された答えを考えましか?

私は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);
    }
}

4

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()
}

1

すべてのタイプの「シミュレータ」を含めるには

NSString *model = [[UIDevice currentDevice] model];
if([model rangeOfString:@"Simulator" options:NSCaseInsensitiveSearch].location !=NSNotFound)
{
    // we are running in a simulator
}

4
これはXcode 7とは関係ありません。iOSシミュレーターをiOS8(Xcode 7から)で実行すると、これは機能します。アプリがiOSシミュレーターから起動された場合、[[UIDevice currentDevice] model]が「iPhone」のみを返すiOS9では機能しません
Stefan

なんで-[NSString containsString]
Gobe 2016年

1

Swift 4.2(Xcode 10)では、これを行うことができます

#if targetEnvironment(simulator)
  //simulator code
#else 
  #warning("Not compiling for simulator")
#endif

1
ちょうどもう1つのコピーペースト
J. Doe

0

私の回答は、@ Daniel Magnussonの回答と、@ Nuthatchと@ n.Drakeのコメントに基づいています。そして私はそれを書いて、iOS9以降で作業する迅速なユーザーのために時間を節約します。

これは私のために働いたものです:

if UIDevice.currentDevice().name.hasSuffix("Simulator"){
    //Code executing on Simulator
} else{
    //Code executing on Device
}

1
ユーザーがSimulatorデバイス名に単語を追加した場合、コードは機能しません
mbelsky

残念ながら、XCode 8 UIDevice.current.nameでは、シミュレーターが実行されているマシンの名前(通常は「SimonのMacBook Pro」など)が報告されるため、テストの信頼性が低下しました。私はまだそれを修正するためのきれいな方法を探しています。
マイケル

0

///デバイスではなくシミュレータの場合はtrueを返します

public static var isSimulator: Bool {
    #if (arch(i386) || arch(x86_64)) && os(iOS)
        return true
    #else
        return false
    #endif
}

0

Appleは、アプリがシミュレーターを対象としていることを確認するためのサポートを次のように追加しました。

#if targetEnvironment(simulator)
let DEVICE_IS_SIMULATOR = true
#else
let DEVICE_IS_SIMULATOR = false
#endif

0

何もうまくいかない場合は、これを試してください

public struct Platform {

    public static var isSimulator: Bool {
        return TARGET_OS_SIMULATOR != 0 // Use this line in Xcode 7 or newer
    }

}

-4

私の意見では、答え(上に提示され、以下に繰り返されます):

NSString *model = [[UIDevice currentDevice] model];
if ([model isEqualToString:@"iPhone Simulator"]) {
    //device is simulator
}

これは、コンパイル時ではなく実行時に実行されるため、最良の答えです。


11
同意しません。このコードは最終的に製品に組み込まれますが、コンパイラディレクティブは-デバイス上で不必要な-ルーチンを排除します。
9石

1
デバイスとシミュレータは完全に異なるコンパイルターゲットであるため、コンパイラディレクティブが機能します。つまり、両方で同じバイナリを使用しません。それは持っている別のハードウェアにコンパイルするので、その場合には意味があります。
Brad Parks

実行時に実行されることは、それが可能な最悪の答えになります。
gnasher729 2016

-4

これは私にとって最もうまくいきました

NSString *name = [[UIDevice currentDevice] name];


if ([name isEqualToString:@"iPhone Simulator"]) {

}

2
Xcode 7.3では、iPhone 6 Plus Simulatorはを返します"iPhone"
エリック
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.