在Objective-C中,我们可以使用宏知道应用程序是为设备还是模拟器构建的:
#if TARGET_IPHONE_SIMULATOR
// Simulator
#else
// Device
#endif
这些是编译时宏,在运行时不可用。
我如何在Swift中实现同样的目标?
在Objective-C中,我们可以使用宏知道应用程序是为设备还是模拟器构建的:
#if TARGET_IPHONE_SIMULATOR
// Simulator
#else
// Device
#endif
这些是编译时宏,在运行时不可用。
我如何在Swift中实现同样的目标?
当前回答
让我在这里澄清一些事情:
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
其他回答
更新信息截至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
斯威夫特4
现在可以使用targetEnvironment(模拟器)作为参数。
#if targetEnvironment(simulator)
// Simulator
#else
// Device
#endif
为Xcode 9.3更新
更新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表达式中使用它,编译器将发出关于不可访问代码的警告。
为了解决这个警告,请参阅其他答案之一。
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