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

Viewed 127078

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.

21 Answers

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.

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

Works for Swift 5 and Xcode 12

Use this code:

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

For Swift 4.2 / xCode 10

I created an extension on UIDevice, so I can easily ask for if the simulator is running.

// 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
    }
}

In my AppDelegate for example I use this method to decide wether registering for remote notification is necessary, which is not possible for the simulator.

// CHECK FOR REAL DEVICE / OR SIMULATOR
if UIDevice.isSimulator() == false {

    // REGISTER FOR SILENT REMOTE NOTIFICATION
    application.registerForRemoteNotifications()
}

I had the same problem, both TARGET_IPHONE_SIMULATOR and TARGET_OS_IPHONE are always defined, and are set to 1. Pete's solution works, of course, but if you ever happen to build on something other than intel (unlikely, but who knows), here's something that's safe as long as the iphone hardware doesn't change (so your code will always work for the iphones currently out there):

#if defined __arm__ || defined __thumb__
#undef TARGET_IPHONE_SIMULATOR
#define TARGET_OS_IPHONE
#else
#define TARGET_IPHONE_SIMULATOR 1
#undef TARGET_OS_IPHONE
#endif

Put that somewhere convenient, and then pretend that the TARGET_* constants were defined correctly.

With Swift 4.2 (Xcode 10), we can do this

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

Apple has added support for checking the app is targeted for the simulator with the following:

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

if nothing worked, try this

public struct Platform {

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

}
Related