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

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

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

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


当前回答

下面是一个基于HotJard上面的精彩答案的Xcode 11 Swift示例,这也添加了一个isDevice Bool,并使用SIMULATOR_UDID而不是name。变量赋值是在每一行上完成的,这样你就可以更容易地在调试器中检查它们。

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

还有DTPlatformName的字典条目,它应该包含模拟器。

其他回答

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

斯威夫特4:

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

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

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

斯威夫特5.2.4 Xcode 11.7


 #if targetEnvironment(simulator)

 #endif

运行时,但比这里的大多数其他解决方案更简单:

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

或者,你可以调用一个Objective-C helper函数来返回一个使用预处理器宏的布尔值(特别是如果你已经在你的项目中混合了)。

编辑:不是最好的解决方案,特别是在Xcode 9.3中。请看HotJard的回答

让我在这里澄清一些事情:

TARGET_OS_SIMULATOR在很多情况下在Swift代码中没有设置;由于桥接头,您可能会意外地导入它,但这是脆弱的,不受支持。这在框架中甚至是不可能的。这就是为什么有些人对这在Swift中是否有效感到困惑。 我强烈建议不要使用架构来代替模拟器。

执行动态检查:

检查ProcessInfo.processInfo。environment["SIMULATOR_DEVICE_NAME"] != nil完全没问题。

您还可以通过检查SIMULATOR_MODEL_IDENTIFIER来获得正在模拟的底层模型,它将返回像iPhone10,3这样的字符串。

执行静态检查:

Xcode 9.2及更早版本:定义你自己的Swift编译标志(如其他答案所示)。

Xcode 9.3+使用新的targetenvirenvironment条件:

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