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

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

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

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


当前回答

更新信息截至2018年2月20日

看起来@russbishop有一个权威的答案,使这个答案“不正确”-即使它似乎工作了很长一段时间。

检测应用程序是否正在构建的设备或模拟器在Swift

以前的回答

基于@WZW的回答和@Pang的评论,我创建了一个简单的实用结构。这个解决方案避免了@WZW的答案产生的警告。

import Foundation

struct Platform {

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

}

使用示例:

if Platform.isSimulator {
    print("Running on Simulator")
}

其他回答

从Swift 1.0开始,对我来说有用的是检查除了arm之外的架构:

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

     //simulator
#else 
     //device

#endif

更新信息截至2018年2月20日

看起来@russbishop有一个权威的答案,使这个答案“不正确”-即使它似乎工作了很长一段时间。

检测应用程序是否正在构建的设备或模拟器在Swift

以前的回答

基于@WZW的回答和@Pang的评论,我创建了一个简单的实用结构。这个解决方案避免了@WZW的答案产生的警告。

import Foundation

struct Platform {

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

}

使用示例:

if Platform.isSimulator {
    print("Running on Simulator")
}

我不知道这是否对任何人有用,但至少M1 mac的当前版本似乎没有将SIMULATOR_MODEL_IDENTIFIER传递到NSProcessInfo

我使用

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

和迅捷的对等物。这可能很脆弱,但很有效。

斯威夫特5.2.4 Xcode 11.7


 #if targetEnvironment(simulator)

 #endif

下面是一个基于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的字典条目,它应该包含模拟器。