[英]How can I programmatically determine if my app is running in the iphone simulator?
As the question states, I would mainly like to know whether or not my code is running in the simulator, but would also be interested in knowing the specific iphone version that is running or being simulated.正如问题所述,我主要想知道我的代码是否在模拟器中运行,但也有兴趣了解正在运行或正在模拟的特定 iphone 版本。
EDIT: I added the word 'programmatically' to the question name.编辑:我在问题名称中添加了“以编程方式”这个词。 The point of my question is to be able to dynamically include / exclude code depending on which version / simulator is running, so I'd really be looking for something like a pre-processor directive that can provide me this info.
我的问题的重点是能够根据正在运行的版本/模拟器动态包含/排除代码,所以我真的会寻找像预处理器指令这样的东西可以为我提供这些信息。
Already asked, but with a very different title.已经问过了,但标题非常不同。
What #defines are set up by Xcode when compiling for iPhone Xcode 在为 iPhone 编译时设置了什么 #defines
I'll repeat my answer from there:我将从那里重复我的回答:
It's in the SDK docs under "Compiling source code conditionally"它位于“有条件地编译源代码”下的 SDK 文档中
The relevant definition is TARGET_OS_SIMULATOR, which is defined in /usr/include/TargetConditionals.h within the iOS framework.相关的定义是TARGET_OS_SIMULATOR,它在iOS框架内的/usr/include/TargetConditionals.h中定义。 On earlier versions of the toolchain, you had to write:
在早期版本的工具链上,您必须编写:
#include "TargetConditionals.h"
but this is no longer necessary on the current (Xcode 6/iOS8) toolchain.但这在当前(Xcode 6/iOS8)工具链上不再需要。
So, for example, if you want to check that you are running on device, you should do因此,例如,如果您想检查您是否在设备上运行,您应该这样做
#if TARGET_OS_SIMULATOR
// Simulator-specific code
#else
// Device-specific code
#endif
depending on which is appropriate for your use-case.取决于哪个适合您的用例。
This is purported to work officially.据说这是正式工作。
#if TARGET_IPHONE_SIMULATOR
NSString *hello = @"Hello, iPhone simulator!";
#elif TARGET_OS_IPHONE
NSString *hello = @"Hello, device!";
#else
NSString *hello = @"Hello, unknown target!";
#endif
This code will tell you if you are running in a simulator.此代码将告诉您是否在模拟器中运行。
#ifdef __i386__
NSLog(@"Running in the simulator");
#else
NSLog(@"Running on a device");
#endif
Not pre-processor directive, but this was what I was looking for when i came to this question;不是预处理器指令,但这正是我遇到这个问题时所寻找的;
NSString *model = [[UIDevice currentDevice] model];
if ([model isEqualToString:@"iPhone Simulator"]) {
//device is simulator
}
The best way to do this is:最好的方法是:
#if TARGET_IPHONE_SIMULATOR
and not而不是
#ifdef TARGET_IPHONE_SIMULATOR
since its always defined: 0 or 1因为它总是定义:0 或 1
THERE IS A BETTER WAY NOW!现在有更好的方法!
As of Xcode 9.3 beta 4 you can use #if targetEnvironment(simulator)
to check.从 Xcode 9.3 beta 4 开始,您可以使用
#if targetEnvironment(simulator)
进行检查。
#if targetEnvironment(simulator)
//Your simulator code
#endif
UPDATE更新
Xcode 10 and iOS 12 SDK supports this too. Xcode 10 和 iOS 12 SDK 也支持这一点。
In case of Swift we can implement following在 Swift 的情况下,我们可以实现以下
We can create struct which allows you to create a structured data我们可以创建允许您创建结构化数据的结构
struct Platform {
static var isSimulator: Bool {
#if targetEnvironment(simulator)
// We're on the simulator
return true
#else
// We're on a device
return false
#endif
}
}
Then If we wanted to Detect if app is being built for device or simulator in Swift then .然后,如果我们想检测应用程序是在 Swift 中为设备还是模拟器构建的,那么 .
if Platform.isSimulator {
// Do one thing
} else {
// Do the other
}
Works for Swift 5
and Xcode 12
适用于
Swift 5
和Xcode 12
Use this code:使用此代码:
#if targetEnvironment(simulator)
// Simulator
#else
// Device
#endif
All those answer are good, but it somehow confuses newbie like me as it does not clarify compile check and runtime check.所有这些答案都很好,但它以某种方式让像我这样的新手感到困惑,因为它没有澄清编译检查和运行时检查。 Preprocessor are before compile time, but we should make it clearer
预处理器在编译时间之前,但我们应该说得更清楚
This blog article shows How to detect the iPhone simulator?这篇博客文章展示了如何检测 iPhone 模拟器? clearly
清楚地
Runtime运行时
First of all, let's shortly discuss.首先,让我们简短地讨论一下。 UIDevice provides you already information about the device
UIDevice 已为您提供有关设备的信息
[[UIDevice currentDevice] model]
will return you “iPhone Simulator” or “iPhone” according to where the app is running.将根据应用程序运行的位置返回“iPhone Simulator”或“iPhone”。
Compile time编译时间
However what you want is to use compile time defines.但是,您想要的是使用编译时定义。 Why?
为什么? Because you compile your app strictly to be run either inside the Simulator or on the device.
因为您严格编译应用程序以在模拟器内或设备上运行。 Apple makes a define called
TARGET_IPHONE_SIMULATOR
. Apple 做了一个名为
TARGET_IPHONE_SIMULATOR
的定义。 So let's look at the code :那么让我们看一下代码:
#if TARGET_IPHONE_SIMULATOR
NSLog(@"Running in Simulator - no app store or giro");
#endif
The previous answers are a little dated.以前的答案有点过时了。 I found that all you need to do is query the
TARGET_IPHONE_SIMULATOR
macro ( no need to include any other header files [assuming you are coding for iOS]).我发现您需要做的就是查询
TARGET_IPHONE_SIMULATOR
宏(无需包含任何其他头文件[假设您正在为 iOS 编码])。
I attempted TARGET_OS_IPHONE
but it returned the same value (1) when running on an actual device and simulator, that's why I recommend using TARGET_IPHONE_SIMULATOR
instead.我尝试了
TARGET_OS_IPHONE
但它在实际设备和模拟器上运行时返回相同的值 (1),这就是我建议使用TARGET_IPHONE_SIMULATOR
的原因。
In swift :迅速:
#if (arch(i386) || arch(x86_64))
...
#endif
From Detect if app is being built for device or simulator in Swift从检测是否正在为 Swift 中的设备或模拟器构建应用程序
For Swift 4.2 / xCode 10对于 Swift 4.2 / xCode 10
I created an extension on UIDevice, so I can easily ask for if the simulator is running.我在 UIDevice 上创建了一个扩展,所以我可以很容易地询问模拟器是否正在运行。
// UIDevice+CheckSimulator.swift
import UIKit
extension UIDevice {
/// Checks if the current device that runs the app is xCode's simulator
static func isSimulator() -> Bool {
#if targetEnvironment(simulator)
return true
#else
return false
#endif
}
}
In my AppDelegate for example I use this method to decide wether registering for remote notification is necessary, which is not possible for the simulator.例如,在我的AppDelegate 中,我使用此方法来决定是否需要注册远程通知,这对于模拟器来说是不可能的。
// CHECK FOR REAL DEVICE / OR SIMULATOR
if UIDevice.isSimulator() == false {
// REGISTER FOR SILENT REMOTE NOTIFICATION
application.registerForRemoteNotifications()
}
I had the same problem, both TARGET_IPHONE_SIMULATOR
and TARGET_OS_IPHONE
are always defined, and are set to 1. Pete's solution works, of course, but if you ever happen to build on something other than intel (unlikely, but who knows), here's something that's safe as long as the iphone hardware doesn't change (so your code will always work for the iphones currently out there):我遇到了同样的问题,
TARGET_IPHONE_SIMULATOR
和TARGET_OS_IPHONE
总是被定义,并设置为 1。当然,Pete 的解决方案是有效的,但如果你碰巧建立在英特尔以外的东西上(不太可能,但谁知道),这里有一些东西只要 iphone 硬件不改变就安全(因此您的代码将始终适用于当前的 iphone):
#if defined __arm__ || defined __thumb__
#undef TARGET_IPHONE_SIMULATOR
#define TARGET_OS_IPHONE
#else
#define TARGET_IPHONE_SIMULATOR 1
#undef TARGET_OS_IPHONE
#endif
Put that somewhere convenient, and then pretend that the TARGET_*
constants were defined correctly.把它放在方便的地方,然后假装
TARGET_*
常量定义正确。
Has anyone considered the answer provided here ?有没有人考虑过这里提供的答案?
I suppose the objective-c equivalent would be我想objective-c的等价物是
+ (BOOL)isSimulator {
NSOperatingSystemVersion ios9 = {9, 0, 0};
NSProcessInfo *processInfo = [NSProcessInfo processInfo];
if ([processInfo isOperatingSystemAtLeastVersion:ios9]) {
NSDictionary<NSString *, NSString *> *environment = [processInfo environment];
NSString *simulator = [environment objectForKey:@"SIMULATOR_DEVICE_NAME"];
return simulator != nil;
} else {
UIDevice *currentDevice = [UIDevice currentDevice];
return ([currentDevice.model rangeOfString:@"Simulator"].location != NSNotFound);
}
}
To include all types of "simulators"包括所有类型的“模拟器”
NSString *model = [[UIDevice currentDevice] model];
if([model rangeOfString:@"Simulator" options:NSCaseInsensitiveSearch].location !=NSNotFound)
{
// we are running in a simulator
}
With Swift 4.2 (Xcode 10), we can do this使用 Swift 4.2 (Xcode 10),我们可以做到这一点
#if targetEnvironment(simulator)
//simulator code
#else
#warning("Not compiling for simulator")
#endif
My answer is based on @Daniel Magnusson answer and comments of @Nuthatch and @n.Drake.我的回答基于@Daniel Magnusson 的回答以及@Nuthatch 和@n.Drake 的评论。 and I write it to save some time for swift users working on iOS9 and onwards.
我写它是为了为在 iOS9 及更高版本上工作的快速用户节省一些时间。
This is what worked for me:这对我有用:
if UIDevice.currentDevice().name.hasSuffix("Simulator"){
//Code executing on Simulator
} else{
//Code executing on Device
}
/// Returns true if its simulator and not a device /// 如果是模拟器而不是设备则返回真
public static var isSimulator: Bool {
#if (arch(i386) || arch(x86_64)) && os(iOS)
return true
#else
return false
#endif
}
Apple has added support for checking the app is targeted for the simulator with the following: Apple 添加了对检查应用程序是否针对模拟器的支持,如下所示:
#if targetEnvironment(simulator)
let DEVICE_IS_SIMULATOR = true
#else
let DEVICE_IS_SIMULATOR = false
#endif
if nothing worked, try this如果没有任何效果,试试这个
public struct Platform {
public static var isSimulator: Bool {
return TARGET_OS_SIMULATOR != 0 // Use this line in Xcode 7 or newer
}
}
This worked for me best这对我最有效
NSString *name = [[UIDevice currentDevice] name];
if ([name isEqualToString:@"iPhone Simulator"]) {
}
In my opinion, the answer (presented above and repeated below):在我看来,答案(在上面提出并在下面重复):
NSString *model = [[UIDevice currentDevice] model];
if ([model isEqualToString:@"iPhone Simulator"]) {
//device is simulator
}
is the best answer because it is obviously executed at RUNTIME versus being a COMPILE DIRECTIVE.是最好的答案,因为它显然是在运行时执行的,而不是编译指令。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.