[英]How can I programmatically determine if my app is running in the iphone simulator?
正如問題所述,我主要想知道我的代碼是否在模擬器中運行,但也有興趣了解正在運行或正在模擬的特定 iphone 版本。
編輯:我在問題名稱中添加了“以編程方式”這個詞。 我的問題的重點是能夠根據正在運行的版本/模擬器動態包含/排除代碼,所以我真的會尋找像預處理器指令這樣的東西可以為我提供這些信息。
已經問過了,但標題非常不同。
Xcode 在為 iPhone 編譯時設置了什么 #defines
我將從那里重復我的回答:
它位於“有條件地編譯源代碼”下的 SDK 文檔中
相關的定義是TARGET_OS_SIMULATOR,它在iOS框架內的/usr/include/TargetConditionals.h中定義。 在早期版本的工具鏈上,您必須編寫:
#include "TargetConditionals.h"
但這在當前(Xcode 6/iOS8)工具鏈上不再需要。
因此,例如,如果您想檢查您是否在設備上運行,您應該這樣做
#if TARGET_OS_SIMULATOR
// Simulator-specific code
#else
// Device-specific code
#endif
取決於哪個適合您的用例。
據說這是正式工作。
#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
不是預處理器指令,但這正是我遇到這個問題時所尋找的;
NSString *model = [[UIDevice currentDevice] model];
if ([model isEqualToString:@"iPhone Simulator"]) {
//device is simulator
}
最好的方法是:
#if TARGET_IPHONE_SIMULATOR
而不是
#ifdef TARGET_IPHONE_SIMULATOR
因為它總是定義:0 或 1
現在有更好的方法!
從 Xcode 9.3 beta 4 開始,您可以使用#if targetEnvironment(simulator)
進行檢查。
#if targetEnvironment(simulator)
//Your simulator code
#endif
更新
Xcode 10 和 iOS 12 SDK 也支持這一點。
在 Swift 的情況下,我們可以實現以下
我們可以創建允許您創建結構化數據的結構
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
}
}
然后,如果我們想檢測應用程序是在 Swift 中為設備還是模擬器構建的,那么 .
if Platform.isSimulator {
// Do one thing
} else {
// Do the other
}
適用於Swift 5
和Xcode 12
使用此代碼:
#if targetEnvironment(simulator)
// Simulator
#else
// Device
#endif
所有這些答案都很好,但它以某種方式讓像我這樣的新手感到困惑,因為它沒有澄清編譯檢查和運行時檢查。 預處理器在編譯時間之前,但我們應該說得更清楚
這篇博客文章展示了如何檢測 iPhone 模擬器? 清楚地
運行時
首先,讓我們簡短地討論一下。 UIDevice 已為您提供有關設備的信息
[[UIDevice currentDevice] model]
將根據應用程序運行的位置返回“iPhone Simulator”或“iPhone”。
編譯時間
但是,您想要的是使用編譯時定義。 為什么? 因為您嚴格編譯應用程序以在模擬器內或設備上運行。 Apple 做了一個名為TARGET_IPHONE_SIMULATOR
的定義。 那么讓我們看一下代碼:
#if TARGET_IPHONE_SIMULATOR
NSLog(@"Running in Simulator - no app store or giro");
#endif
以前的答案有點過時了。 我發現您需要做的就是查詢TARGET_IPHONE_SIMULATOR
宏(無需包含任何其他頭文件[假設您正在為 iOS 編碼])。
我嘗試了TARGET_OS_IPHONE
但它在實際設備和模擬器上運行時返回相同的值 (1),這就是我建議使用TARGET_IPHONE_SIMULATOR
的原因。
對於 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_*
常量定義正確。
有沒有人考慮過這里提供的答案?
我想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);
}
}
包括所有類型的“模擬器”
NSString *model = [[UIDevice currentDevice] model];
if([model rangeOfString:@"Simulator" options:NSCaseInsensitiveSearch].location !=NSNotFound)
{
// we are running in a simulator
}
使用 Swift 4.2 (Xcode 10),我們可以做到這一點
#if targetEnvironment(simulator)
//simulator code
#else
#warning("Not compiling for simulator")
#endif
我的回答基於@Daniel Magnusson 的回答以及@Nuthatch 和@n.Drake 的評論。 我寫它是為了為在 iOS9 及更高版本上工作的快速用戶節省一些時間。
這對我有用:
if UIDevice.currentDevice().name.hasSuffix("Simulator"){
//Code executing on Simulator
} else{
//Code executing on Device
}
/// 如果是模擬器而不是設備則返回真
public static var isSimulator: Bool {
#if (arch(i386) || arch(x86_64)) && os(iOS)
return true
#else
return false
#endif
}
Apple 添加了對檢查應用程序是否針對模擬器的支持,如下所示:
#if targetEnvironment(simulator)
let DEVICE_IS_SIMULATOR = true
#else
let DEVICE_IS_SIMULATOR = false
#endif
如果沒有任何效果,試試這個
public struct Platform {
public static var isSimulator: Bool {
return TARGET_OS_SIMULATOR != 0 // Use this line in Xcode 7 or newer
}
}
這對我最有效
NSString *name = [[UIDevice currentDevice] name];
if ([name isEqualToString:@"iPhone Simulator"]) {
}
在我看來,答案(在上面提出並在下面重復):
NSString *model = [[UIDevice currentDevice] model];
if ([model isEqualToString:@"iPhone Simulator"]) {
//device is simulator
}
是最好的答案,因為它顯然是在運行時執行的,而不是編譯指令。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.