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

问题描述

更新 30/01/19

虽然这个答案可能有效,但推荐的静态检查解决方案(正如几位 Apple 工程师所阐明的那样)是定义一个针对 iOS 模拟器的自定义编译器标志。

原始答案

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

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

版本之后

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

如需更多说明,您可以查看 提案SE-0190


-

显然,这在设备上是错误的,但它为 iOS 模拟器返回 true,如文档中所述:

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

如果您正在为 iOS 以外的模拟器进行开发,您可以简单地更改os参数:例如

检测 模拟器

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

检测 模拟器

#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变量(或TARGET_IPHONE_SIMULATOR在 iOS 8 及更低版本中),这在模拟器上是真实的。

请注意,这与使用预处理器标志不同,并且受限制程度略高。例如,您将无法在 aif/else语法无效的地方使用它(例如,在函数范围之外)。

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

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

此外,由于 swift 预处理器将标志替换为 a0或 a 1,如果您直接在if/else表达式中使用它,编译器将引发有关无法访问代码的警告。

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

解决方法

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

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

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

我怎样才能在 Swift 中达到同样的效果?

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...