How can I programmatically determine if my app is running in the iphone simulator?

125,895

Solution 1

Already asked, but with a very different title.

What #defines are set up by Xcode when compiling for iPhone

I'll repeat my answer from there:

It's in the SDK docs under "Compiling source code conditionally"

The relevant definition is TARGET_OS_SIMULATOR, which is defined in /usr/include/TargetConditionals.h within the iOS framework. On earlier versions of the toolchain, you had to write:

#include "TargetConditionals.h"

but this is no longer necessary on the current (Xcode 6/iOS8) toolchain.

So, for example, if you want to check that you are running on device, you should do

#if TARGET_OS_SIMULATOR
    // Simulator-specific code
#else
    // Device-specific code
#endif

depending on which is appropriate for your use-case.

Solution 2

Updated code:

This is purported to work officially.

#if TARGET_IPHONE_SIMULATOR
NSString *hello = @"Hello, iPhone simulator!";
#elif TARGET_OS_IPHONE
NSString *hello = @"Hello, device!";
#else
NSString *hello = @"Hello, unknown target!";
#endif

Original post (since deprecated)

This code will tell you if you are running in a simulator.

#ifdef __i386__
NSLog(@"Running in the simulator");
#else
NSLog(@"Running on a device");
#endif

Solution 3

Not pre-processor directive, but this was what I was looking for when i came to this question;

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

Solution 4

The best way to do this is:

#if TARGET_IPHONE_SIMULATOR

and not

#ifdef TARGET_IPHONE_SIMULATOR

since its always defined: 0 or 1

Solution 5

THERE IS A BETTER WAY NOW!

As of Xcode 9.3 beta 4 you can use #if targetEnvironment(simulator) to check.

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

UPDATE
Xcode 10 and iOS 12 SDK supports this too.

Share:
125,895

Related videos on Youtube

Jeffrey Meyer
Author by

Jeffrey Meyer

Technology Entrepreneur

Updated on September 22, 2020

Comments

  • Jeffrey Meyer
    Jeffrey Meyer over 3 years

    As the question states, I would mainly like to know whether or not my code is running in the simulator, but would also be interested in knowing the specific iphone version that is running or being simulated.

    EDIT: I added the word 'programmatically' to the question name. The point of my question is to be able to dynamically include / exclude code depending on which version / simulator is running, so I'd really be looking for something like a pre-processor directive that can provide me this info.

    • WiseOldDuck
      WiseOldDuck about 8 years
      I'm not sure a pre-processor directive is dynamic (though it might be what you were looking for anyway). The directive means that you actually knew, when you built it, where it was going to wind up running.
    • rustyMagnet
      rustyMagnet over 3 years
      As I know my target is only a new iPhone or Simulator, I like __x86_64__ ( iPhone simulator ) and __arm64__ ( iPhone device )
  • Jeffrey Meyer
    Jeffrey Meyer over 15 years
    Thanks. I agree with you this is a more specific version of your original question. If yours had come up in my original search, I wouldn't have even needed to ask.
  • Airsource Ltd
    Airsource Ltd over 15 years
    Yes, I appreciate that it doesn't show up easily in a search - I was just referencing it as a duplicate so that people could read comments in both places.
  • Vadim
    Vadim over 15 years
    Be careful with these definitions. When you compile code with menu item 'Project > Set Active SDK > Simulator…', as TARGET_IPHONE_SIMULATOR as TARGET_OS_IPHONE variables are both defined! So the only right way to separate logic is pointed out below by Pete (Thanks dude).
  • Airsource Ltd
    Airsource Ltd over 15 years
    Correct, but when you compile for device, TARGET_IPHONE_SIMULATOR is not set, so why not just switch on that? Switching on i386 relies on the toolchain defs, and will be invalid if compiling on a non-x86 platform (not currently possibly, of course).
  • Anton
    Anton over 14 years
    Watch the #if and #ifdef difference. For me it was the cause of incorrect behavior.
  • user102008
    user102008 over 13 years
    [model compare:iPhoneSimulator] == NSOrderedSame should be written as [model isEqualToString:iPhoneSimulator]
  • cyrilchampier
    cyrilchampier almost 12 years
    as said here: stackoverflow.com/questions/3742525/… it is not true for static libraries
  • nine stones
    nine stones over 10 years
    I disagree. This code ends up in your product, whereas a compiler directive keeps the - on the device unnecessary - routine out.
  • dmur
    dmur about 10 years
    Perhaps the need to include TargetConditionals has been obviated since this was written, but just wanted to note that #if TARGET_IPHONE_SIMULATOR works without including TargetConditionals.h now.
  • Brad Parks
    Brad Parks about 10 years
    The compiler directives work because the device and simulators are completely different compile targets - ie you wouldn't use the same binary on both. It has to be compiled to different hardware, so it makes sense in that case.
  • mmmmmm
    mmmmmm almost 10 years
    How does this improve on other answers?
  • onmyway133
    onmyway133 almost 10 years
    @Mark It clarifies a little bit
  • Nuthatch
    Nuthatch almost 10 years
    Or [model hasSuffix:@"Simulator"] if you only care about "simulator" in general, not iPhone or iPad in particular. This answer won't work for iPad simulator :)
  • malhal
    malhal over 9 years
    As of iOS 8 and Xcode 6.1.1 the TARGET_OS_IPHONE is true on the simulator.
  • Le Mot Juiced
    Le Mot Juiced about 9 years
    Upvoted because Nuthatch's comment makes this the best answer in toto.
  • JoJo
    JoJo almost 9 years
    Wouldn't it better to use the regular if instead of the pre-processor #if so that you have to potential to get compiler errors in both control paths? The pre-processor #if doesn't compile the branch that you're currently not targeting. You wouldn't want to have a false sense of accomplishment when all your code works on the simulator, but your real device branch is broken.
  • Airsource Ltd
    Airsource Ltd almost 9 years
    You may be #if-ing code that doesn't actually compile on one platform or the other, but yes, you could use if. Not sure how this helps with the false sense of achievement, you would still need to test it on both platforms!
  • nsinvocation
    nsinvocation over 8 years
    It has nothing to do with Xcode 7. If you run iOS Simulator with iOS8 (from Xcode 7) then this will work. It won't work for iOS9 where [[UIDevice currentDevice] model] returns only "iPhone" if app was launched from iOS Simulator
  • n.Drake
    n.Drake over 8 years
    In iOS9, check the device name instead of model
  • eMdOS
    eMdOS over 8 years
    Currently, in Xcode 7, iOS 9 Simulator [[UIDevice currentDevice] model] is returning iPhone also instead of iPhone Simulator. So, I think this is not the best approach.
  • Fabio Napodano
    Fabio Napodano over 8 years
    this doesn't worik anymore on newer XCode versions
  • gnasher729
    gnasher729 about 8 years
    Unless you are in 2016 and run a 64 bit simulator. Or in 2019 and run your code on an iPhone with Intel processor.
  • gnasher729
    gnasher729 about 8 years
    TARGET_OS_IPHONE is for code that might run on iOS or on MacOS X. Obviously you would want that code to behave the "iPhone" way on a simulator.
  • gnasher729
    gnasher729 about 8 years
    Being executed at RUNTIME makes it the worst possible answer.
  • Dimitris
    Dimitris about 8 years
    Why the parentheses ( ) around TARGET_OS_SIMULATOR?
  • mbelsky
    mbelsky about 8 years
    The code won't work if a user adds Simulator word in his device name
  • mbelsky
    mbelsky about 8 years
    The code won't work if a user adds Simulator word in his device name
  • Eric
    Eric about 8 years
    On Xcode 7.3, iPhone 6 Plus Simulator returns "iPhone".
  • Iron John Bonney
    Iron John Bonney almost 8 years
    Cleanest implementation in my opinion, and it accounts for x86_64 and i386 architectures. Helped me overcome a weird device vs. simulator bug in Core Data. You're the man!
  • Andrew Duncan
    Andrew Duncan almost 8 years
    I needed the include in an Obj-C file for iOS 9 using Xcode 7. Hmm.
  • Michael
    Michael over 7 years
    Unfortunately with XCode 8 UIDevice.current.name reports the name of the machine the Simulator is running on (typically something like "Simon's MacBook Pro" now) so the test has become unreliable. I am still looking into a clean way to fix it.
  • Bobjt
    Bobjt over 7 years
    To distinguish between mac apps: #if ( arch( i386 ) || arch( x86_64 ) ) && !os( OSX ) // we’re on a simulator running on mac, and not a mac app. (For cross platforms code included in mac targets)
  • Gobe
    Gobe over 7 years
    why not -[NSString containsString]?
  • Airsource Ltd
    Airsource Ltd about 7 years
  • Airsource Ltd
    Airsource Ltd about 7 years
    @Dimitris It's good practice. You don't know how TARGET_OS_SIMULATOR has been defined, so !(TARGET_OS_SIMULATOR) may not be identical to !TARGET_OS_SIMULATOR
  • DawnSong
    DawnSong over 6 years
    In Playground, you will get a warning, "Code after 'return' will never be executed". So I think #if #else #endif will be better.
  • Vrutin Rathod
    Vrutin Rathod about 6 years
    This is the only that works for me, rest of the solutions didn't work.
  • Stefan Vasiljevic
    Stefan Vasiljevic over 5 years
    There is a better way to do this now. See my answer in this thread stackoverflow.com/a/49236898/2272561
  • J. Doe
    J. Doe over 5 years
    Just another copy paste
  • Matt S.
    Matt S. about 4 years
    Note This is only in swift.