如何以编程方式确定我的应用程序是否在iphone模拟器中运行?

Jef*_*yer 263 xcode objective-c ios ios-simulator swift

正如问题所述,我主要想知道我的代码是否在模拟器中运行,但也有兴趣了解正在运行或正在模拟的特定iphone版本.

编辑:我在问题名称中添加了"以编程方式"这个词.我的问题是能够动态地包含/排除代码,具体取决于正在运行的版本/模拟器,所以我真的在寻找类似于预处理器指令的东西,它可以为我提供这些信息.

Air*_*Ltd 352

已经问过了,但标题却截然不同.

在为iPhone编译时,Xcode设置了哪些#defines

我会从那里重复我的回答:

它位于"有条件地编译源代码"下的SDK文档中

相关定义是TARGET_OS_SIMULATOR,它在iOS框架中的/usr/include/TargetConditionals.h中定义.在早期版本的工具链中,您必须编写:

#include "TargetConditionals.h"
Run Code Online (Sandbox Code Playgroud)

但是当前(Xcode 6/iOS8)工具链不再需要这个.

因此,例如,如果要检查是否在设备上运行,则应该这样做

#if TARGET_OS_SIMULATOR
    // Simulator-specific code
#else
    // Device-specific code
#endif
Run Code Online (Sandbox Code Playgroud)

取决于哪个适合您的用例.

  • 自编写之后,可能已经避免了包含TargetConditionals的需要,但只是想注意#if TARGET_IPHONE_SIMULATOR现在可以在不包含TargetConditionals.h的情况下工作. (7认同)
  • 小心这些定义.使用菜单项"Project> Set Active SDK> Simulator ..."编译代码时,TARGET_IPHONE_SIMULATOR作为TARGET_OS_IPHONE变量都被定义了!因此Pete(谢谢老兄)在下面指出了分离逻辑的唯一正确方法. (5认同)
  • 观察#if和#ifdef的区别.对我来说,这是不正确行为的原因. (5认同)

Pet*_*ete 106

更新的代码:

据称这是正式的.

#if TARGET_IPHONE_SIMULATOR
NSString *hello = @"Hello, iPhone simulator!";
#elif TARGET_OS_IPHONE
NSString *hello = @"Hello, device!";
#else
NSString *hello = @"Hello, unknown target!";
#endif
Run Code Online (Sandbox Code Playgroud)

原帖(自弃之后)

此代码将告诉您是否在模拟器中运行.

#ifdef __i386__
NSLog(@"Running in the simulator");
#else
NSLog(@"Running on a device");
#endif
Run Code Online (Sandbox Code Playgroud)

  • 从iOS 8和Xcode 6.1.1开始,TARGET_OS_IPHONE在模拟器上为true. (7认同)
  • 对于较新的XCode版本,这不再浪费了 (3认同)

Dan*_*son 61

不是预处理器指令,但这是我在寻找这个问题时所寻找的;

NSString *model = [[UIDevice currentDevice] model];
if ([model isEqualToString:@"iPhone Simulator"]) {
    //device is simulator
}
Run Code Online (Sandbox Code Playgroud)

  • 或者``model hasSuffix:@"Simulator"]`如果你只关心"模拟器"一般,而不是**iPhone**或**iPad**.这个答案不适用于iPad模拟器:) (18认同)
  • 不再适用于iOS9的模拟器! (11认同)
  • 在iOS9中,检查设备`name`而不是`model` (11认同)
  • `[model compare:iPhoneSimulator] == NSOrderedSame`应该写成`[model isEqualToString:iPhoneSimulator]` (9认同)
  • 如果用户在其设备名称中添加“模拟器”字样,则代​​码将不起作用 (2认同)

Tar*_*nfx 55

最好的方法是:

#if TARGET_IPHONE_SIMULATOR
Run Code Online (Sandbox Code Playgroud)

并不是

#ifdef TARGET_IPHONE_SIMULATOR
Run Code Online (Sandbox Code Playgroud)

因为它始终定义:0或1


Ste*_*vic 37

现在有一个更好的方式!

从Xcode 9.3 beta 4开始,您可以使用它#if targetEnvironment(simulator)进行检查.

#if targetEnvironment(simulator)
//Your simulator code
#endif
Run Code Online (Sandbox Code Playgroud)

更新
Xcode 10和iOS 12 SDK也支持此功能.

  • 这应该是新接受的答案. (4认同)
  • 这是唯一对我有用的解决方案,其余的解决方案都不起作用。 (2认同)

Nis*_*ada 33

对于Swift,我们可以实现以下内容

我们可以创建允许您创建结构化数据的struct

struct Platform {
    static let isSimulator: Bool = {
        #if arch(i386) || arch(x86_64)
            return true
        #endif
        return false
    }()
}
Run Code Online (Sandbox Code Playgroud)

然后,如果我们想要检测是否正在为Swift中的设备或模拟器构建应用程序.

if Platform.isSimulator {
    // Do one thing
}
else {
    // Do the other
}
Run Code Online (Sandbox Code Playgroud)

  • 在Playground中,您将收到一条警告,"返回后的代码将永远不会被执行".所以我觉得`#if #else #endif`会更好. (5认同)

onm*_*133 9

所有这些答案都很好,但它有点像我这样的新手,因为它没有澄清编译检查和运行时检查.预编译器在编译之前,但我们应该更清楚

这篇博客文章展示了如何检测iPhone模拟器?明确地

运行

首先,我们稍后讨论一下.UIDevice已经为您提供了有关该设备的信息

[[UIDevice currentDevice] model]
Run Code Online (Sandbox Code Playgroud)

将根据应用程序运行的位置返回"iPhone模拟器"或"iPhone".

编译时间

但是你想要的是使用编译时定义.为什么?因为您严格编译应用程序以在模拟器内或设备上运行.Apple定义了一个名为 TARGET_IPHONE_SIMULATOR.那么让我们来看看代码:

#if TARGET_IPHONE_SIMULATOR

NSLog(@"Running in Simulator - no app store or giro");

#endif
Run Code Online (Sandbox Code Playgroud)

  • 目前,在Xcode 7中,iOS 9模拟器`[[UIDevice currentDevice] model]`正在返回`iPhone`而不是'iPhone模拟器'.所以,我认为这不是最好的方法. (5认同)

Har*_*dim 8

适用于Swift 4Xcode 9.4.1

使用此代码:

#if targetEnvironment(simulator)
   // Simulator
#else
   // Device
#endif
Run Code Online (Sandbox Code Playgroud)


Stu*_*ner 6

以前的答案有点过时了.我发现您需要做的就是查询TARGET_IPHONE_SIMULATOR宏(不需要包含任何其他头文件 [假设您正在为iOS编码]).

我尝试TARGET_OS_IPHONE但是当它在实际设备和模拟器上运行时它返回了相同的值(1),这就是我推荐使用的原因TARGET_IPHONE_SIMULATOR.


Vij*_*rma 5

有人考虑过这里提供的答案吗?

我想 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);
    }
}
Run Code Online (Sandbox Code Playgroud)


Luk*_*ker 5

对于 Swift 4.2 / xCode 10

我在 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
    }
}
Run Code Online (Sandbox Code Playgroud)

例如,在我的AppDelegate 中,我使用此方法来决定是否需要注册远程通知,这对于模拟器来说是不可能的。

// CHECK FOR REAL DEVICE / OR SIMULATOR
if UIDevice.isSimulator() == false {

    // REGISTER FOR SILENT REMOTE NOTIFICATION
    application.registerForRemoteNotifications()
}
Run Code Online (Sandbox Code Playgroud)