在Objective-C中,我们可以知道是否正在使用宏为设备或模拟器构建应用程序:
#if TARGET_IPHONE_SIMULATOR
// Simulator
#else
// Device
#endif
Run Code Online (Sandbox Code Playgroud)
这些是编译时宏,在运行时不可用.
我怎样才能在Swift中实现同样的目标?我搜索了堆栈溢出,看了一下docs并且无法搞清楚.
Gab*_*lla 324
虽然这个答案可能有效,但静态检查的推荐解决方案(由几位Apple工程师澄清)是定义一个针对iOS模拟器的自定义编译器标志.有关如何操作的详细说明,请参阅@ mbelsky的答案.
如果您需要静态检查(例如,不是运行时if/else)您无法直接检测模拟器,但您可以在桌面架构上检测iOS,如下所示
#if (arch(i386) || arch(x86_64)) && os(iOS)
...
#endif
Run Code Online (Sandbox Code Playgroud)
经过Swift 4.1版本
最新的使用,现在直接适用于所有类型的模拟器的所有条件 - 只需要应用一个条件 -
#if targetEnvironment(simulator)
// your simulator code
#else
// your real device code
#endif
Run Code Online (Sandbox Code Playgroud)
有关更多说明,您可以查看Swift提案SE-0190
对于旧版本 -
显然,这在设备上是错误的,但对于iOS模拟器,它返回true,如文档中所指定:
当为32位iOS模拟器编译代码时,arch(i386)构建配置返回true.
如果您正在开发iOS以外的模拟器,您可以简单地改变os参数:例如
检测watchOS模拟器
#if (arch(i386) || arch(x86_64)) && os(watchOS)
...
#endif
Run Code Online (Sandbox Code Playgroud)
检测tvOS模拟器
#if (arch(i386) || arch(x86_64)) && os(tvOS)
...
#endif
Run Code Online (Sandbox Code Playgroud)
或者,甚至,检测任何模拟器
#if (arch(i386) || arch(x86_64)) && (os(iOS) || os(watchOS) || os(tvOS))
...
#endif
Run Code Online (Sandbox Code Playgroud)
如果您对运行时检查没有问题,则可以检查TARGET_OS_SIMULATOR变量(或TARGET_IPHONE_SIMULATOR在iOS 8及更低版本中),这在模拟器上是真实的.
请注意,这与使用预处理程序标志不同,稍微有限.例如,您将无法在if/else语法无效的位置使用它(例如,在函数范围之外).
例如,假设您希望在设备和模拟器上具有不同的导入.通过动态检查这是不可能的,而静态检查则是微不足道的.
#if (arch(i386) || arch(x86_64)) && os(iOS)
import Foo
#else
import Bar
#endif
Run Code Online (Sandbox Code Playgroud)
此外,由于标志被一个0或一个1swift预处理器替换,如果您直接在if/else表达式中使用它,编译器将发出有关无法访问代码的警告.
要解决此警告,请参阅其他答案之一.
mbe*_*sky 167
过时的SWIFT 4.1.请#if targetEnvironment(simulator)改用.资源
要在Swift中检测模拟器,您可以使用构建配置:
现在您可以使用此语句来检测模拟器:
#if IOS_SIMULATOR
print("It's an iOS Simulator")
#else
print("It's a device")
#endif
Run Code Online (Sandbox Code Playgroud)
你也可以扩展UIDevice类:
extension UIDevice {
var isSimulator: Bool {
#if IOS_SIMULATOR
return true
#else
return false
#endif
}
}
// Example of usage: UIDevice.current.isSimulator
Run Code Online (Sandbox Code Playgroud)
Dan*_*iel 156
更新的信息截至2018年2月20日
看起来@russbishop有一个权威的答案,使得这个答案"不正确" - 即使它似乎工作了很长时间.
上一个答案
根据@ WZW的回答和@Pang的评论,我创建了一个简单的实用程序结构.这个解决方案避免了@ WZW回答的警告.
import Foundation
struct Platform {
static var isSimulator: Bool {
return TARGET_OS_SIMULATOR != 0
}
}
Run Code Online (Sandbox Code Playgroud)
用法示例:
if Platform.isSimulator {
print("Running on Simulator")
}
Run Code Online (Sandbox Code Playgroud)
Hot*_*ard 67
来自Xcode 9.3
#if targetEnvironment(simulator)
Run Code Online (Sandbox Code Playgroud)
Swift支持具有单个有效参数模拟器的新平台条件targetEnvironment.现在可以使用"#if targetEnvironment(simulator)"形式的条件编译来检测构建目标何时是模拟器.当通过现有的os()和arch()平台条件评估似乎间接测试模拟器环境的平台条件时,Swift编译器将尝试检测,警告并建议使用targetEnvironment(模拟器).(SE-0190)
iOS 9+:
extension UIDevice {
static var isSimulator: Bool {
return NSProcessInfo.processInfo().environment["SIMULATOR_DEVICE_NAME"] != nil
}
}
Run Code Online (Sandbox Code Playgroud)
斯威夫特3:
extension UIDevice {
static var isSimulator: Bool {
return ProcessInfo.processInfo.environment["SIMULATOR_DEVICE_NAME"] != nil
}
}
Run Code Online (Sandbox Code Playgroud)
在iOS 9之前:
extension UIDevice {
static var isSimulator: Bool {
return UIDevice.currentDevice().model == "iPhone Simulator"
}
}
Run Code Online (Sandbox Code Playgroud)
Objective-C的:
@interface UIDevice (Additions)
- (BOOL)isSimulator;
@end
@implementation UIDevice (Additions)
- (BOOL)isSimulator {
if([[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){9, 0, 0}]) {
return [NSProcessInfo processInfo].environment[@"SIMULATOR_DEVICE_NAME"] != nil;
} else {
return [[self model] isEqualToString:@"iPhone Simulator"];
}
}
@end
Run Code Online (Sandbox Code Playgroud)
Mat*_*ift 54
您现在可以targetEnvironment(simulator)用作参数.
#if targetEnvironment(simulator)
// Simulator
#else
// Device
#endif
Run Code Online (Sandbox Code Playgroud)
针对Xcode 9.3进行了更新
hec*_*ill 38
斯威夫特 5.2.4 Xcode 11.7
#if targetEnvironment(simulator)
#endif
Run Code Online (Sandbox Code Playgroud)
rus*_*hop 34
让我在这里澄清一些事情:
TARGET_OS_SIMULATOR在很多情况下,Swift代码中没有设置; 由于桥接头可能会意外地导入它,但这很脆弱而且不受支持.它甚至在框架中也是不可能的.这就是为什么有些人对Swift是否有效感到困惑.要执行动态检查:
检查ProcessInfo.processInfo.environment["SIMULATOR_DEVICE_NAME"] != nil完全没问题.
您还可以通过检查SIMULATOR_MODEL_IDENTIFIER哪些将返回字符串来获取正在模拟的基础模型iPhone10,3.
要执行静态检查:
Xcode 9.2及更早版本:定义自己的Swift编译标志(如其他答案所示).
Xcode 9.3+使用新的targetEnvironment条件:
#if targetEnvironment(simulator)
// for sim only
#else
// for device
#endif
Run Code Online (Sandbox Code Playgroud)
aka*_*aru 15
什么对我有用,因为Swift 1.0正在检查除arm之外的架构:
#if arch(i386) || arch(x86_64)
//simulator
#else
//device
#endif
Run Code Online (Sandbox Code Playgroud)
shi*_*him 14
运行时,但比其他大多数解决方案简单:
if TARGET_OS_SIMULATOR != 0 {
// target is current running in the simulator
}
Run Code Online (Sandbox Code Playgroud)
或者,您可以调用Objective-C辅助函数,该函数返回使用预处理器宏的布尔值(特别是如果您已经在项目中混合).
编辑:不是最好的解决方案,特别是从Xcode 9.3开始.请参阅HotJard的回答
在现代系统中:
#if targetEnvironment(simulator)
// sim
#else
// device
#endif
Run Code Online (Sandbox Code Playgroud)
这很简单.
我希望这个扩展能派上用场。
extension UIDevice {
static var isSimulator: Bool = {
#if targetEnvironment(simulator)
return true
#else
return false
#endif
}()
}
Run Code Online (Sandbox Code Playgroud)
用法:
if UIDevice.isSimulator {
print("running on simulator")
}
Run Code Online (Sandbox Code Playgroud)
Xcode 11、斯威夫特 5
#if !targetEnvironment(macCatalyst)
#if targetEnvironment(simulator)
true
#else
false
#endif
#endif
Run Code Online (Sandbox Code Playgroud)
TARGET_IPHONE_SIMULATOR在iOS 9中已弃用.TARGET_OS_SIMULATOR是替代品.也TARGET_OS_EMBEDDED可以.
来自TargetConditionals.h:
Run Code Online (Sandbox Code Playgroud)#if defined(__GNUC__) && ( defined(__APPLE_CPP__) || defined(__APPLE_CC__) || defined(__MACOS_CLASSIC__) ) . . . #define TARGET_OS_SIMULATOR 0 #define TARGET_OS_EMBEDDED 1 #define TARGET_IPHONE_SIMULATOR TARGET_OS_SIMULATOR /* deprecated */ #define TARGET_OS_NANO TARGET_OS_WATCH /* deprecated */