27

Any sample code that would show me how to, in my iPhone application code:

  1. How to detect if the application has just been DEPLOYED to be run to a simulator (and not a device) [if "Deployed" isn't available, then just detecting when the app is being run on the simulator as opposed to a device)
  2. Where about in my iPhone app code would I put the lines that setup my test data in the simulator - this is noting I wanted the test data to be effectively wiped clean/re-instated each time I recompile and push to the simulator (however I didn't really want this code to be run during my usage of the application in the simulator - e.g. should be able to swap apps in the simulator & then when I start my app again in the simulator it should not run the data setup code

Any other better suggestions re how to cover off managing this test data on the simulator would be good. Background here is that I'm talking about test data in the Calendar (e.g. using Event Kit), so I don't want to have the app putting calendar items into my iPhone when I deploy to my device (sorry - only have 1 personal iPhone here).

tshepang
  • 12,111
  • 21
  • 91
  • 136
Greg
  • 34,042
  • 79
  • 253
  • 454

4 Answers4

50

I obviously do use something like this ...

#import <TargetConditionals.h>

#if TARGET_IPHONE_SIMULATOR

// Simulator specific code

#else // TARGET_IPHONE_SIMULATOR

// Device specific code

#endif // TARGET_IPHONE_SIMULATOR

And to your second question ... Something like this should help you. In your app delegate:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  if ( ! [[NSUserDefaults standardUserDefaults] boolForKey:@"initialized"] ) {
    // Setup stuff
    [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"initialized"];
  }

  ... your code ...
}
zrzka
  • 20,249
  • 5
  • 47
  • 73
  • thanks - so re 2: where in the code (i.e. which method) could I put this setup code so it only runs when I start the app for the first time? i.e. it doesn't run again if I jump to App B then back to my App. However I assume when I killed the app off (double clicking on iPhone button etc) that when I clicked on the app again this would be classed as running for the first time. Hope this makes sense. – Greg Feb 25 '11 at 20:41
  • Just edited my answer. You need some flag to know if your application was initialized or not. I did show you how to do this with user defaults, but there many ways how to do this. – zrzka Feb 25 '11 at 20:47
  • ok thanks - so you're implying there's nothing in an iPhone life-cycle model (i.e. with states, messages) that inherently differentiates then? i.e. you pretty much have to code it yourself? - Also if you did (say on the simulator) delete the application (i.e. kill the process I guess), then would this code work here? i.e. would it really remove NSUserDefaults? – Greg Feb 25 '11 at 20:59
  • NSUserDefaults are removed when you remove your application from simulator/device. – zrzka Feb 25 '11 at 21:02
  • Killing process doesn't mean application delete. It just stops working and you can start it again, even from Xcode. – zrzka Feb 25 '11 at 21:05
  • 3
    2015 update: `TARGET_IPHONE_SIMULATOR` is now deprecated and `TARGET_OS_SIMULATOR` should be used instead. – Dev-iL Oct 04 '15 at 23:52
16

Swift 5:

TARGET_OS_SIMULATOR does not work in Swift 5. targetEnvironment(simulator) works, like below:

#if targetEnvironment(simulator)
// code to run if running on simulator
#else
// code to run if not running on simulator
#endif

Reference

12

If you'd like to check on runtime (instead compile time with the # compiler macro) use this code:

UIDevice *currentDevice = [UIDevice currentDevice];
if ([currentDevice.model rangeOfString:@"Simulator"].location == NSNotFound) {
    //running on device
} else { 
    // running in Simulator
}

see also this question: How can I programmatically determine if my app is running in the iphone simulator?

Community
  • 1
  • 1
mahal tertin
  • 3,239
  • 24
  • 41
  • 4
    This is no longer correct. currentDevice.model will now return "iPhone" or "iPad". I guess this has changed in recent SDK updates. We use `sysctlbyname("hw.machine")` and compare return value to x86_64. – gilm Nov 30 '15 at 15:12
2

The code block that worked for me:

#if defined(__i386__)  || defined(__x86_64__)
    /* Run code if in Simulator */
#else
    /* Run code if in device */
#end

I noticed __i386__ does not work for iPhone 6 simulators, so I added x86_64

Roozbeh Zabihollahi
  • 7,207
  • 45
  • 39
  • Using this technique is fragile because it will require updating whenever Apple updates their platforms. The technique specified by robertvojta is more reliable. – ThomasW Jan 05 '16 at 08:12
  • That's true. But easier to use, because you do not need an import. Also, it is not that common for Apple to add a new platform. – Roozbeh Zabihollahi Jan 05 '16 at 22:45
  • I guess it doesn't work anymore in M1 Macs. Please update your answer. – pieroxy Jan 10 '22 at 17:28
  • @pieroxy what would be the equivalent in M1? – Roozbeh Zabihollahi Apr 04 '22 at 18:08
  • @RoozbehZabihollahi I haven't got the slightlest clue. This is so complicated and unreliable that I think we should not try to guess, it's just a disaster waiting to happen. – pieroxy Apr 05 '22 at 12:48
  • 1
    This still works on M1 macs, since currently the iOS Simulator is an X86 application. If you're using Swift, the same is written like this: `#if arch(i386) || arch(x86_64) ...` – keccs May 30 '22 at 08:34