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

编辑:我在问题名称中添加了“以编程方式”这个词。我的问题的要点是能够动态包括/排除代码取决于哪个版本/模拟器正在运行,所以我真的在寻找像一个预处理程序指令,可以为我提供这个信息。


当前回答

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

我想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);
    }
}

其他回答

更新后的代码:

官方声称这是有效的。

#if TARGET_IPHONE_SIMULATOR
NSString *hello = @"Hello, iPhone simulator!";
#elif TARGET_OS_IPHONE
NSString *hello = @"Hello, device!";
#else
NSString *hello = @"Hello, unknown target!";
#endif

原帖(已弃用)

这段代码将告诉您是否在模拟器中运行。

#ifdef __i386__
NSLog(@"Running in the simulator");
#else
NSLog(@"Running on a device");
#endif

我的回答是基于@Daniel Magnusson的回答和@Nuthatch和@n.Drake的评论。我写它是为了为在iOS9及以后的系统上快速工作的用户节省一些时间。

这对我来说很管用:

if UIDevice.currentDevice().name.hasSuffix("Simulator"){
    //Code executing on Simulator
} else{
    //Code executing on Device
}

我已经问过了,但题目完全不同。

Xcode在为iPhone编译时设置了什么#定义

我将重复我的回答:

在SDK文档中的“有条件地编译源代码”

相关的定义是TARGET_OS_SIMULATOR,它在iOS框架中的/usr/include/ targetconditions .h中定义。在工具链的早期版本中,你必须这样写:

#include "TargetConditionals.h"

但在当前(Xcode 6/iOS8)的工具链中,这不再是必要的。

例如,如果你想检查你是否在设备上运行,你应该这样做

#if TARGET_OS_SIMULATOR
    // Simulator-specific code
#else
    // Device-specific code
#endif

这取决于哪个适合您的用例。

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
    }
}

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

// CHECK FOR REAL DEVICE / OR SIMULATOR
if UIDevice.isSimulator() == false {
        
    // REGISTER FOR SILENT REMOTE NOTIFICATION
    application.registerForRemoteNotifications()
}

我有同样的问题,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

把它放在方便的地方,然后假装TARGET_*常量是正确定义的。