在Objective-C中,我们可以使用宏知道应用程序是为设备还是模拟器构建的:

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

这些是编译时宏,在运行时不可用。

我如何在Swift中实现同样的目标?


当前回答

斯威夫特4:

目前,我更喜欢使用ProcessInfo类来知道设备是否是模拟器以及正在使用的设备类型:

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

但是,正如您所知道的,simModelCode并不是一个容易理解的代码,因此,如果您需要,您可以尝试查看另一个so答案,以确定当前的iPhone/设备模型,并获得一个更适合人类阅读的字符串。

其他回答

swift 4.1已过时。请改用#if targetEnvironment(模拟器)。源

要检测Swift中的模拟器,您可以使用构建配置:

在Swift Compiler中定义此配置- d IOS_SIMULATOR - Custom Flags >其他Swift Flags 在下拉菜单中选择Any iOS Simulator SDK

现在你可以使用这个语句来检测模拟器:

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

你也可以扩展UIDevice类:

extension UIDevice {
    var isSimulator: Bool {
        #if IOS_SIMULATOR
            return true
        #else
            return false
        #endif
    }
}
// Example of usage: UIDevice.current.isSimulator

更新30/01/19

虽然这个答案可能有效,但静态检查的推荐解决方案(正如几个苹果工程师所澄清的那样)是定义一个针对iOS模拟器的自定义编译器标志。有关如何操作的详细说明,请参阅@mbelsky的回答。

原来的答案

如果你需要静态检查(例如,不是运行时If /else),你不能直接检测模拟器,但你可以在桌面架构上检测iOS,如下所示

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

Swift 4.1版本之后

最新的使用,现在直接适用于所有在一个条件下所有类型的模拟器只需要适用一个条件-

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

要了解更多信息,请查看Swift提案SE-0190


旧版本-

显然,这在设备上是false,但对于iOS模拟器,它返回true,如文档中所指定的:

当为32位iOS模拟器编译代码时,arch(i386)构建配置返回true。

如果你正在为iOS以外的模拟器开发,你可以简单地改变操作系统参数:

检测watchOS模拟器

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

检测tvOS模拟器

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

或者,甚至检测任何模拟器

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

如果您可以使用运行时检查,则可以检查TARGET_OS_SIMULATOR变量(或iOS 8及以下版本的TARGET_IPHONE_SIMULATOR),这在模拟器上是正确的。

请注意,这与使用预处理器标志有所不同,并且有一些限制。例如,你不能在if/else语法无效的地方使用它(例如,在函数作用域之外)。

例如,假设您希望在设备和模拟器上有不同的导入。这在动态检查中是不可能的,而在静态检查中是微不足道的。

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

此外,由于该标志被swift预处理器替换为0或1,如果你直接在if/else表达式中使用它,编译器将发出关于不可访问代码的警告。

为了解决这个警告,请参阅其他答案之一。

Xcode 11, Swift 5

    #if !targetEnvironment(macCatalyst)
    #if targetEnvironment(simulator)
        true
    #else
        false        
    #endif
    #endif

使用下面的代码:

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

适用于Swift 4和Xcode 9.4.1

我在Swift 3中使用了下面的代码

if TARGET_IPHONE_SIMULATOR == 1 {
    //simulator
} else {
    //device
}