How to find out if your iPhone app is running in the iPhone Simulator

Posted by Dave on December 12th, 2008

Sometimes it is useful to run different code when your iPhone application is being tested in the iPhone Simulator rather than on a real iPhone or iPod Touch device. For example, if you are testing CoreLocation functionality in the Simulator, all of CoreLocation’s returned locations will be for somewhere in Cupertino – not much use for testing with non-US data.

Checking for the Simulator is pretty simple, as shown in the code below.

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

(This is a major edit of my original article, with many thanks to H from OfCodeAndMen, who pointed out that my original approach was rubbish, and suggested the approach above instead.)



Write a Comment

Take a moment to comment and tell us what you think. Some basic HTML is allowed for formatting.

Reader Comments

Don’t use __i386__. For many reasons. In this case, one of the obvious is either if the iPhone goes i386 or the Mac changes its CPU. Or something along those lines.

There is a _documented_ way to do what you want to. The following code works:
#if TARGET_IPHONE_SIMULATOR
NSString *hello = @”Hello, iPhone simulator!”;
#elif TARGET_OS_IPHONE
NSString *hello = @”Hello, device!”;
#else
NSString *hello = @”Hello, unknown target!”;
#endif

Well, I looked all over and couldn’t find that anywhere. Ah well. Thanks for the info.

Just to clarify – my original post suggested checking for __i386__ and forking your code based on whether it is set or not. H pointed out that this is a Bad Idea, so I’ve updated the post to reflect his much better suggestion instead. Full credit to H for the correction.

This code doesn’t actually work properly. TARGET_OS_IPHONE also works in the emulator because the iPhone emulator runs the iPhone OS. The only reason this code works in your example is because you’re checking for the emulator first. If you checked the device first, your code would fail.

If you’re in the emulator you’re code says:
#if TRUE
NSString *hello = @”Hello, iPhone simulator!”;
#elif TRUE
NSString *hello = @”Hello, device!”;
#else // ALWAYS TRUE
NSString *hello = @”Hello, unknown target!”;
#endif

Since the first “if” clause is true, it never gets to the second one. If you’re on the device and you run this your code says:

#if FALSE
NSString *hello = @”Hello, iPhone simulator!”;
#elif TRUE
NSString *hello = @”Hello, device!”;
#else // ALWAYS TRUE
NSString *hello = @”Hello, unknown target!”;
#endif

Since the first if statement fails, you default to the second which makes it seem like you’re on the phone when in fact the second statement is true even when you’re running in the emulator. You can test this by making a bunch of #if/#endif statements instead of an #if/#elif/#else/#endif statment.

The proper code looks like this
#if TARGET_OS_IPHONE && TARGET_IPHONE_SIMULATOR
NSString *hello = @”Hello, iPhone simulator!”;
#elif TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR
NSString *hello = @”Hello, device!”;
#else
NSString *hello = @”Hello, unknown target!”;
#endif

Hi Joe,

So you’re saying that the code I posted (with thanks to H) *does* work absolutely fine, but it’s not as logically explicit as it could be? Thanks for the alternative!