如何在Swift中检测是否正在为设备或模拟器构建应用程序 [英] How to detect if app is being built for device or simulator in Swift
问题描述
在Objective-C中,我们可以知道是否正在使用宏为设备或模拟器构建应用程序:
In Objective-C we can know if an app is being built for device or simulator using macros:
#if TARGET_IPHONE_SIMULATOR
// Simulator
#else
// Device
#endif
这些是编译时宏,在运行时不可用.
These are compile time macros and not available at runtime.
如何在Swift中实现相同目标?
推荐答案
更新30/01/19
尽管此答案可能有效,但建议进行静态检查的解决方案(如几位Apple工程师所阐明的那样)是定义一个针对iOS模拟器的自定义编译器标志.有关如何执行此操作的详细说明,请参见 @mbelsky的答案.
如果您需要静态检查(例如,如果不是运行时if/else),则无法直接检测到模拟器,但可以在如下所示的桌面体系结构上检测iOS
If you need a static check (e.g. not a runtime if/else) you can't detect the simulator directly, but you can detect iOS on a desktop architecture like follows
#if (arch(i386) || arch(x86_64)) && os(iOS)
...
#endif
Swift 4.1 版本
After Swift 4.1 version
最新用途,现在可以在一种情况下直接针对所有类型的模拟器使用所有条件-
#if targetEnvironment(simulator)
// your simulator code
#else
// your real device code
#endif
更多说明,您可以查看 Swift 提案
对于旧版本-
Clearly, this is false on a device, but it returns true for the iOS Simulator, as specified in the documentation:
为32位iOS模拟器编译代码时,arch(i386)构建配置将返回true.
The arch(i386) build configuration returns true when the code is compiled for the 32–bit iOS simulator.
如果您是为iOS以外的模拟器开发的,则只需更改os
参数:例如
If you are developing for a simulator other than iOS, you can simply vary the os
parameter: e.g.
检测 watchOS 模拟器
#if (arch(i386) || arch(x86_64)) && os(watchOS)
...
#endif
检测 tvOS 模拟器
#if (arch(i386) || arch(x86_64)) && os(tvOS)
...
#endif
或者甚至可以检测到任何模拟器
Or, even, detect any simulator
#if (arch(i386) || arch(x86_64)) && (os(iOS) || os(watchOS) || os(tvOS))
...
#endif
如果可以运行时检查,可以检查TARGET_OS_SIMULATOR
变量(在iOS 8及以下版本中为TARGET_IPHONE_SIMULATOR
),这在模拟器上是正确的.
If you instead are ok with a runtime check, you can inspect the TARGET_OS_SIMULATOR
variable (or TARGET_IPHONE_SIMULATOR
in iOS 8 and below), which is truthy on a simulator.
请注意,这与使用预处理器标志不同,并且有更多限制.例如,在if/else
语法上无效的地方(例如,在函数作用域之外),您将无法使用它.
Please notice that this is different and slightly more limited than using a preprocessor flag. For instance you won't be able to use it in place where a if/else
is syntactically invalid (e.g. outside of functions scopes).
例如,说您要在设备和模拟器上具有不同的导入.对于动态检查,这是不可能的,而对于静态检查,这是微不足道的.
Say, for example, that you want to have different imports on the device and on the simulator. This is impossible with a dynamic check, whereas it's trivial with a static check.
#if (arch(i386) || arch(x86_64)) && os(iOS)
import Foo
#else
import Bar
#endif
此外,由于该标志被快速预处理器替换为0
或1
,因此,如果直接在if/else
表达式中使用它,则编译器将发出有关代码无法到达的警告.
Also, since the flag is replaced with a 0
or a 1
by the swift preprocessor, if you directly use it in a if/else
expression the compiler will raise a warning about unreachable code.
要变通解决此警告,请参阅其他答案之一.
In order to work around this warning, see one of the other answers.
这篇关于如何在Swift中检测是否正在为设备或模拟器构建应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!