347

In Objective-C we can know if an app is being built for device or simulator using macros:

#if TARGET_IPHONE_SIMULATOR
    // Simulator
#else
    // Device
#endif

These are compile time macros and not available at runtime.

How can I achieve the same in Swift?

Rafał Sroka
  • 39,540
  • 23
  • 113
  • 143
  • 10
    THE HIGHEST VOTED ANSWERS ARE NOT THE BEST WAY TO SOLVE THIS PROBLEM! mbelsky's answer (currently very far down) is the only solution that comes without any pitfalls. Even Greg Parker from Apple suggested to do it that way: https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160125/007960.html – jan.vogt May 22 '16 at 12:20
  • 1
    EVEN IN CAPS, IT IS NAIVE TO SUGGEST THAT THERE IS ANYTHING WRONG WITH A RUNTIME CHECK. Suggestions by Apple engineers are often poorly-thought out garbage, or only apply in certain situations, so that initself means less than nothing. – Fattie Dec 30 '17 at 15:38
  • 1
    @Fattie: It would be interesting to know why none of the given answers satisfies your needs, and what you are exactly hoping for by offering the bounty. – Martin R Dec 30 '17 at 17:53
  • hey @MartinR, the QA is incredibly old / dated and needs to be updated. – Fattie Jan 02 '18 at 13:12

21 Answers21

469

Update 30/01/19

While this answer may work, the recommended solution for a static check (as clarified by several Apple engineers) is to define a custom compiler flag targeting iOS Simulators. For detailed instructions on how to do to it, see @mbelsky's answer.

Original answer

If you need a static check (e.g. not a runtime if/else) you can't detect the simulator directly, but you can detect iOS on a desktop architecture like follows

#if (arch(i386) || arch(x86_64)) && os(iOS)
    ...
#endif

After Swift 4.1 version

Latest use, now directly for all in one condition for all types of simulators need to apply only one condition -

#if targetEnvironment(simulator)
  // your simulator code
#else
  // your real device code
#endif

For more clarification, you can check Swift proposal SE-0190


For older version -

Clearly, this is false on a device, but it returns true for the iOS Simulator, as specified in the documentation:

The arch(i386) build configuration returns true when the code is compiled for the 32–bit iOS simulator.

If you are developing for a simulator other than iOS, you can simply vary the os parameter: e.g.

Detect the watchOS simulator

#if (arch(i386) || arch(x86_64)) && os(watchOS)
...
#endif

Detect the tvOS simulator

#if (arch(i386) || arch(x86_64)) && os(tvOS)
...
#endif

Or, even, detect any simulator

#if (arch(i386) || arch(x86_64)) && (os(iOS) || os(watchOS) || os(tvOS))
...
#endif

If you instead are ok with a runtime check, you can inspect the TARGET_OS_SIMULATOR variable (or TARGET_IPHONE_SIMULATOR in iOS 8 and below), which is truthy on a simulator.

Please notice that this is different and slightly more limited than using a preprocessor flag. For instance you won't be able to use it in place where a if/else is syntactically invalid (e.g. outside of functions scopes).

Say, for example, that you want to have different imports on the device and on the simulator. This is impossible with a dynamic check, whereas it's trivial with a static check.

#if (arch(i386) || arch(x86_64)) && os(iOS)
  import Foo
#else
  import Bar
#endif

Also, since the flag is replaced with a 0 or a 1 by the swift preprocessor, if you directly use it in a if/else expression the compiler will raise a warning about unreachable code.

In order to work around this warning, see one of the other answers.

Anand Nimje
  • 6,163
  • 4
  • 24
  • 43
Gabriele Petronella
  • 106,943
  • 21
  • 217
  • 235
  • 1
    [More reading here](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithCAPIs.html#//apple_ref/doc/uid/TP40014216-CH8-XID_21). And to be even more restrictive, you could use `arch(i386) && os(iOS)`. – ahruss Jul 21 '14 at 16:07
  • 1
    This did not work for me. I had to check for both i386 and x86_64 – akaru Sep 28 '14 at 20:07
  • in Xcode7 beta, UIDevice.currentDevice().model is returned with "iPhone" – LiangWang Jun 18 '15 at 13:36
  • @Jacky thanks, I've decided to remove that solution from the answer since it's just a bad idea. – Gabriele Petronella Jun 18 '15 at 14:10
  • what about the watch simulator? where is the list of all os(?) possibilities? thanks – dowi Nov 01 '15 at 21:05
  • @dowi, I've updated my answer to cover watchOS and tvOS ;) – Gabriele Petronella Nov 02 '15 at 10:01
  • How is detecting the specific architecture superior to merely checking `TARGET_OS_SIMULATOR != 0`? – Dan Rosenstark Mar 14 '16 at 21:20
  • This is a very shaky way of detecting the simulator. Better to use the macro provided by Apple for this purpose, rather than looking at the assembly language? – markshiz Apr 04 '16 at 18:08
  • @markshiz I'm aware this is not super reliable. What macro are you talking about? Apple may have added after my answer, and I'd be happy to change it to a more reliable solution – Gabriele Petronella Apr 04 '16 at 18:11
  • @DanRosenstark just saw the comment. It has a couple of benefits that I've just highlighted in my edit: first you don't need to work around a warning (not a big deal, but still), and most importantly your solution would be a dynamic check, which is different than a pre-compiler step. More in the answer above. – Gabriele Petronella Apr 04 '16 at 23:13
  • 1
    @markshiz see my latest edit. I'm not sure whether this is what you're referring to, but checking the value of `TARGET_OS_SIMULATOR` at runtime is different than a preprocessor step. – Gabriele Petronella Apr 04 '16 at 23:17
  • can the #if (arch(i386) || arch(x86_64)) && os(iOS) be defined as some sort of macro so that you can just call #if ifSimulator, like you could in objective-c?, without having to create an objective-c file and then bridge the header that is. – Oscar Gomez May 03 '16 at 19:51
  • 1
    @OscarGomez I'm afraid swift doesn't allow such flexibility. – Gabriele Petronella May 04 '16 at 11:12
  • 3
    THIS ANSWER IS NOT THE BEST WAY TO SOLVE THIS PROBLEM! mbelsky's answer (currently very far down) is the only solution that comes without any pitfalls. Even Greg Parker from Apple suggested to do it that way: https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160125/007960.html – jan.vogt May 22 '16 at 12:19
  • This is terrible advice and no one should use this answer under any circumstances. – russbishop Sep 14 '17 at 20:26
  • 2
    @russbishop this proved to be helpful advice to hundreds of people so far, compensating for a missing API. Instead of hijacking the answer by signing a comment on top, just communicate. I updated the answer to clarify this is no longer an up-to-date solution and I've provided a link to the one that looks more correct. – Gabriele Petronella Sep 14 '17 at 20:54
  • 9
    In Swift 4.1, you'll be able to say `#if targetEnvironment(simulator)` :) (https://github.com/apple/swift-evolution/blob/master/proposals/0190-target-environment-platform-condition.md) – Hamish Dec 31 '17 at 12:31
  • check this answer: https://stackoverflow.com/questions/24869481/detect-if-app-is-being-built-for-device-or-simulator-in-swift?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa#answer-49634190 – quemeful May 23 '18 at 14:55
206

OUTDATED FOR SWIFT 4.1. Use #if targetEnvironment(simulator) instead. Source

To detect simulator in Swift you can use build configuration:

  • Define this configuration -D IOS_SIMULATOR in Swift Compiler - Custom Flags > Other Swift Flags
  • Select Any iOS Simulator SDK in this drop down Drop down list

Now you could use this statement to detect simulator:

#if IOS_SIMULATOR
    print("It's an iOS Simulator")
#else
    print("It's a device")
#endif

Also you could extend UIDevice class:

extension UIDevice {
    var isSimulator: Bool {
        #if IOS_SIMULATOR
            return true
        #else
            return false
        #endif
    }
}
// Example of usage: UIDevice.current.isSimulator
mbelsky
  • 6,093
  • 2
  • 26
  • 34
  • 9
    This should be the best answer! Even Greg Parker from Apple suggested that way: https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160125/007960.html – jan.vogt May 22 '16 at 12:14
  • 1
    usage update for swift 3: UIDevice.current.isSimulator – tylernol Dec 08 '16 at 18:37
  • 1
    May i ask why if i add this under *Release* this doesn't work? – William Hu Mar 07 '17 at 08:48
  • 4
    This is the only correct answer. You can also set this up in `xcconfig` files by using `OTHER_SWIFT_FLAGS = TARGET_OS_EMBEDDED` and `OTHER_SWIFT_FLAGS[sdk=embeddedsimulator*] = TARGET_OS_SIMULATOR` to override for the Simulator. – russbishop Sep 14 '17 at 20:25
  • 1
    On Xcode 9.2, this answer was failing to compile some of the time. Removing the "-" before the "D" solved the issue for me. – Blake Dec 19 '17 at 16:04
  • Pretty good answer! This way is really future proof! Thanks :) – blackjacx Feb 15 '18 at 14:29
  • Terrific answer! I really like the extension of UIDevice because it makes the added code seem like a natural part of the framework. Worked properly with Swift 4.1 and Xcode 9.3. – user212514 Apr 11 '18 at 14:14
  • check this answer: https://stackoverflow.com/questions/24869481/detect-if-app-is-being-built-for-device-or-simulator-in-swift?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa#answer-49634190 – quemeful May 23 '18 at 14:55
171

Updated Info as of February 20, 2018

It looks like @russbishop has an authoritative answer that renders this answer "incorrect" - even though it appeared to work for a long time.

Detect if app is being built for device or simulator in Swift

Previous Answer

Based on @WZW's answer and @Pang's comments, I created a simple utility struct. This solution avoids warning produced by @WZW's answer.

import Foundation

struct Platform {

    static var isSimulator: Bool {
        return TARGET_OS_SIMULATOR != 0
    }

}

Example usage:

if Platform.isSimulator {
    print("Running on Simulator")
}
Daniel
  • 8,794
  • 4
  • 48
  • 71
  • 11
    Much better solution than accepted one. Indeed if some day (even though it's very unlikely) Apple decide to use i386 or x85_64 on iOS devices, the accepted answer won't work… or even if desktop computers get a new proc! – Frizlab Feb 20 '16 at 23:09
  • 2
    Confirmed that this works perfectly on Xcode 7: `public let IS_SIMULATOR = (TARGET_OS_SIMULATOR != 0)`... same thing, simplified. +1 thanks – Dan Rosenstark Mar 14 '16 at 21:21
  • 1
    @daniel This works well and it's actually more straightforward than my solution. However it's worth noting that it's more limited than an actual preprocessor step. If you need some part of the code not to be included in the target (e.g. you want to choose between two imports at compile time), you have to use a static check. I've edited my answer to highlight this difference. – Gabriele Petronella Apr 04 '16 at 23:21
  • THIS ANSWER IS NOT THE BEST WAY TO SOLVE THIS PROBLEM! mbelsky's answer (currently very far down) is the only solution that comes without any pitfalls. Even Greg Parker from Apple suggested to do it that way: https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160125/007960.html – jan.vogt May 22 '16 at 12:19
  • Maybe `return NSNumber(int: TARGET_OS_SIMULATOR).boolValue` – Gabriel.Massana Sep 28 '16 at 09:44
  • jan dude - EVEN IN CAPS, IT IS NAIVE TO SUGGEST THAT THERE IS ANYTHING WRONG WITH A SIMPLE RUNTIME CHECK USING THE MACRO SUPPLIED FOR AND ONLY FOR THAT EXACT PURPOSE. :) Suggestions by Apple engineers are often poorly-thought out garbage, or only apply in certain situations, so that initself means less than nothing. Simply checking OS_SIMULATOR != 0 is often the K.I.S.S. solution to a trivial problem if you're just fiddling with something during development - indeed in a large project you wouldn't muck about with flags without having to document it, have a meeting etc. – Fattie Dec 30 '17 at 15:43
  • 3
    @Fattie `TARGET_OS_SIMULATOR != 0` is **already in the answer**. It's the solution given by Daniel. There's no need to add it again in a free variable, it's already there. If you think having it in a struct is bad and having it in a free variable is better then post a comment about this or make your own answer. Thanks. – Eric Aya Dec 30 '17 at 17:10
  • TARGET_OS_SIMULATOR is not necessarily set in Swift code so this answer doesn't actually work. – russbishop Feb 19 '18 at 17:39
  • check this answer: https://stackoverflow.com/questions/24869481/detect-if-app-is-being-built-for-device-or-simulator-in-swift?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa#answer-49634190 – quemeful May 23 '18 at 14:55
  • hi @russbishop , that sounds like important information, thanks ! – Fattie Jul 27 '18 at 13:19
  • `static let isSimulator = (TARGET_OS_SIMULATOR != 0)` – sabiland Oct 15 '21 at 10:24
78

Swift 4

You can now use targetEnvironment(simulator) as an argument.

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

Updated for Xcode 9.3

Ahmad F
  • 30,560
  • 17
  • 97
  • 143
JDev
  • 5,168
  • 6
  • 40
  • 61
  • 15
    This should now be the accepted answer. I wish there was a way on SO to propose a new suggested answer based on updates to OS / programming languages. – quemeful May 23 '18 at 14:54
  • 6
    it's a great point @quemeful - it's one of the few basic failings of SO. Since computing systems change so quickly, **almost every answer on SO becomes wrong over time**. – Fattie Jul 27 '18 at 13:23
72

From Xcode 9.3

#if targetEnvironment(simulator)

Swift supports a new platform condition targetEnvironment with a single valid argument simulator. Conditional compilation of the form '#if targetEnvironment(simulator)' can now be used to detect when the build target is a simulator. The Swift compiler will attempt to detect, warn, and suggest the use of targetEnvironment(simulator) when evaluating platform conditions that appear to be testing for simulator environments indirectly, via the existing os() and arch() platform conditions. (SE-0190)

iOS 9+:

extension UIDevice {
    static var isSimulator: Bool {
        return NSProcessInfo.processInfo().environment["SIMULATOR_DEVICE_NAME"] != nil
    }
}

Swift 3:

extension UIDevice {
    static var isSimulator: Bool {
        return ProcessInfo.processInfo.environment["SIMULATOR_DEVICE_NAME"] != nil
    }
}

Before iOS 9:

extension UIDevice {
    static var isSimulator: Bool {
        return UIDevice.currentDevice().model == "iPhone Simulator"
    }
}

Objective-C:

@interface UIDevice (Additions)
- (BOOL)isSimulator;
@end

@implementation UIDevice (Additions)

- (BOOL)isSimulator {
    if([[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){9, 0, 0}]) {
        return [NSProcessInfo processInfo].environment[@"SIMULATOR_DEVICE_NAME"] != nil;
    } else {
        return [[self model] isEqualToString:@"iPhone Simulator"];
    }
}

@end
HotJard
  • 4,598
  • 2
  • 36
  • 36
56

Let me clarify some things here:

  1. TARGET_OS_SIMULATOR is not set in Swift code in many cases; you may be accidentally getting it imported due to a bridging header but this is brittle and not supported. It also isn't even possible in frameworks. This is why some people are confused about whether this works in Swift.
  2. I strongly advise against using architecture as a substitute for simulator.

To perform dynamic checks:

Checking ProcessInfo.processInfo.environment["SIMULATOR_DEVICE_NAME"] != nil is perfectly fine.

You can also get the underlying model being simulated by checking SIMULATOR_MODEL_IDENTIFIER which will return strings like iPhone10,3.

To perform static checks:

Xcode 9.2 & earlier: define your own Swift compilation flag (as shown in other answers).

Xcode 9.3+ use the new targetEnvironment condition:

#if targetEnvironment(simulator)
    // for sim only
#else
    // for device
#endif
russbishop
  • 16,587
  • 7
  • 61
  • 74
  • 1
    It looks like you have some new inside info here. Very helpful! Note TARGET_OS_SIMULATOR worked for quite some time in both app and framework code; and it's also working in Xcode 9.3 b3. But, I guess this is "accidental". Kind of a bummer; because this seems like the least hacky way. As a provider of framework code that could be compiled in either Xcode 9.3 or earlier, it looks like we will have to wrap #if targetEnvironment... in a #if swift(>=4.1) macro to avoid compiler errors. Or I guess use ....environment["SIMULATOR_DEVICE_NAME"] != nil. This check seems more hacky, IMO. – Daniel Feb 20 '18 at 23:51
  • if have " Unexpected platform condition (expected 'os', 'arch', or 'swift') " error using targetEnvironment(simulator) – Zaporozhchenko Oleksandr Mar 27 '18 at 03:07
  • @Aleksandr `targetEnvironment` landed in Xcode 9.3. You need a newer version of Xcode. – russbishop Apr 10 '18 at 16:15
  • @russbishop good work clearing this up for the latest new era - thanks! – Fattie Jul 27 '18 at 13:24
  • 1
    I sent a 250 bounty, since this answer seems to add the most and newest information - cheers – Fattie Jul 31 '18 at 14:33
31

Swift 5.2.4 Xcode 11.7


 #if targetEnvironment(simulator)

 #endif

hectorsvill
  • 681
  • 8
  • 7
16

Runtime, but simpler than most of the other solutions here:

if TARGET_OS_SIMULATOR != 0 {
    // target is current running in the simulator
}

Alternatively, you can just call an Objective-C helper function that returns a boolean that uses the preprocessor macro (especially if you're already mixing in your project).

Edit: Not the best solution, especially as of Xcode 9.3. See HotJard's answer

shim
  • 9,289
  • 12
  • 69
  • 108
  • 3
    I do this but get warnings in the else clause because it "will never be executed". We have a zero warning rule, so :-( – EricS Mar 22 '17 at 20:48
  • it will show a warning but it makes sense, depending if you have simulator or device selected for building, the warning will show on the part that wont be executed, but yeah annoying for a zero warning policy – Fonix Dec 19 '17 at 08:36
  • 1
    Only seeing warnings when I use `== 0` instead of `!= 0`. Using it as written above, even with an `else` block after, does not produce any warnings in Swift 4 Xcode Version 9.2 (9C40b) – shim Dec 19 '17 at 20:41
  • Also I tested it running on a simulator target as well as a physical device. Also seems to be the same in Swift 3.2 (same Xcode version). – shim Dec 19 '17 at 20:46
  • In Xcode 9.3 + Swift 4.1 I just noticed that it does have the warning even with !=0. Sheesh. – shim Apr 13 '18 at 05:16
  • Xcode 9.4.1 and not seeing the warning anymore… I'm getting dizzy… – shim Jun 19 '18 at 14:03
16

I hope this extension comes handy.

extension UIDevice {
    static var isSimulator: Bool = {
        #if targetEnvironment(simulator)
        return true
        #else
        return false
        #endif
    }()
}

Usage:

if UIDevice.isSimulator {
    print("running on simulator")
}
Arsen Khachaturyan
  • 7,904
  • 4
  • 42
  • 42
Lucas Chwe
  • 2,578
  • 27
  • 17
  • @ChetanKoli, I was going for making the code very clear, rather than short, so its easy to understand for anyone. Not sure how i feel about your edit. – Lucas Chwe Dec 18 '19 at 18:52
  • Why make it runtime check? Regular way reqires the same amount of code (just `#if` instead of `if`), but can simplify compilation. Why make it `static var`? Accessing static variables of `UIDevice` generates a warning. Why make it a stored `var`? When would you need to change it? Does it even compile? – user28434'mstep Aug 18 '23 at 18:48
15

What works for me since Swift 1.0 is checking for an architecture other than arm:

#if arch(i386) || arch(x86_64)

     //simulator
#else 
     //device

#endif
Community
  • 1
  • 1
akaru
  • 6,299
  • 9
  • 63
  • 102
12

In modern systems:

#if targetEnvironment(simulator)
    // sim
#else
    // device
#endif

It's dat easy.

Fattie
  • 27,874
  • 70
  • 431
  • 719
  • 1
    Not sure why the first one should be "more correct" than [Daniel's answer](https://stackoverflow.com/a/30284266/1187415). – Note that the second one *is* a compile time check. Happy New Year! – Martin R Jan 02 '18 at 13:45
5

TARGET_IPHONE_SIMULATOR is deprecated in iOS 9. TARGET_OS_SIMULATOR is the replacement. Also TARGET_OS_EMBEDDED is available.

From TargetConditionals.h :

#if defined(__GNUC__) && ( defined(__APPLE_CPP__) || defined(__APPLE_CC__) || defined(__MACOS_CLASSIC__) )
. . .
#define TARGET_OS_SIMULATOR         0
#define TARGET_OS_EMBEDDED          1 
#define TARGET_IPHONE_SIMULATOR     TARGET_OS_SIMULATOR /* deprecated */
#define TARGET_OS_NANO              TARGET_OS_WATCH /* deprecated */ 
Nuthatch
  • 3,597
  • 4
  • 24
  • 17
5

Xcode 11, Swift 5

    #if !targetEnvironment(macCatalyst)
    #if targetEnvironment(simulator)
        true
    #else
        false        
    #endif
    #endif
webcpu
  • 3,174
  • 2
  • 24
  • 17
3

In Xcode 7.2 (and earlier but I haven't tested how much earlier), you can set a platform specific build flag "-D TARGET_IPHONE_SIMULATOR" for "Any iOS Simulator".

Look in the project build settings under "Swift Compiler - Customer Flags" and then set the flag in "Other Swift Flags". You can set a platform specific flag by clicking the 'plus' icon when you hover over a build configuration.

There are a couple of advantages of doing it this way: 1) You can use the same conditional test ("#if TARGET_IPHONE_SIMULATOR") in your Swift and Objective-C code. 2) You can compile out variables that only apply to each build.

Xcode build settings screenshot

xgerrit
  • 31
  • 2
3

All described here Darwin.TargetConditionals: https://github.com/apple/swift-corelibs-foundation/blob/master/CoreFoundation/Base.subproj/SwiftRuntime/TargetConditionals.h

TARGET_OS_SIMULATOR - Generated code will run under a simulator

dimpiax
  • 12,093
  • 5
  • 62
  • 45
3

Use this below code:

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

Works for Swift 4 and Xcode 9.4.1

Haroldo Gondim
  • 7,725
  • 9
  • 43
  • 62
3

Swift 4:

Currently, I prefer to use the ProcessInfo class to know if the device is a simulator and which kind of device is in use:

if let simModelCode = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] {
            print("yes is a simulator :\(simModelCode)")
}

But, as you know, simModelCode isn't a comfortable code to understand immediatly which kind of simulator was launched so, if your need, you can try to see this other SO answer to determine the current iPhone/device model and to have a more human readable string.

Alessandro Ornano
  • 34,887
  • 11
  • 106
  • 133
3

Here is an Xcode 11 Swift example based off of HotJard's awesome answer above, this also adds an isDevice Bool and uses SIMULATOR_UDID instead of name. Variable assignments are done on each line so that you can more easily examine them in the debugger if you choose to.

import Foundation

// Extensions to UIDevice based on ProcessInfo.processInfo.environment keys
// to determine if the app is running on an actual device or the Simulator.

@objc extension UIDevice {
    static var isSimulator: Bool {
        let environment = ProcessInfo.processInfo.environment
        let isSimulator = environment["SIMULATOR_UDID"] != nil
        return isSimulator
    }

    static var isDevice: Bool {
        let environment = ProcessInfo.processInfo.environment
        let isDevice = environment["SIMULATOR_UDID"] == nil
        return isDevice
    }
}

There also is the dictionary entry of DTPlatformName which should contain simulator.

Alex Zavatone
  • 4,106
  • 36
  • 54
3

In addition to other answers.

In Objective-c, Just make sure you included TargetConditionals.

#include <TargetConditionals.h>

before using TARGET_OS_SIMULATOR.

M. Adam
  • 108
  • 5
2

I used this below code in Swift 3

if TARGET_IPHONE_SIMULATOR == 1 {
    //simulator
} else {
    //device
}
ak_ninan
  • 721
  • 7
  • 15
0

I do not know if this will be useful to anyone, but at least the current version of M1 macs do not seem to pass the SIMULATOR_MODEL_IDENTIFIER into NSProcessInfo

I used

BOOL isMobile = [[NSProcessInfo processInfo].environment[@"USER"] isEqual:@"mobile"];

and swift equivalent. This may be fragile but it works.

Olcay Ertaş
  • 5,987
  • 8
  • 76
  • 112
zenchemical
  • 115
  • 1
  • 7