¿Cómo puedo determinar mediante programación si mi aplicación se está ejecutando en el simulador de iPhone?
-
19-08-2019 - |
Pregunta
Como dice la pregunta, principalmente me gustaría saber si mi código se está ejecutando o no en el simulador, pero también estaría interesado en conocer la versión específica de iPhone que se está ejecutando o simulando.
EDITAR: agregué la palabra 'programáticamente' al nombre de la pregunta. El punto de mi pregunta es poder incluir / excluir dinámicamente el código dependiendo de la versión / simulador que se esté ejecutando, por lo que realmente estaría buscando algo como una directiva de preprocesador que pueda proporcionarme esta información.
Solución
Ya preguntado, pero con un título muy diferente.
¿Qué #defines configura Xcode cuando compilando para iPhone
Repetiré mi respuesta desde allí:
Está en los documentos del SDK en " Compilación de código fuente condicionalmente "
La definición relevante es TARGET_OS_SIMULATOR, que se define en /usr/include/TargetConditionals.h dentro del marco de iOS. En versiones anteriores de la cadena de herramientas, tenía que escribir:
#include "TargetConditionals.h"
pero esto ya no es necesario en la cadena de herramientas actual (Xcode 6 / iOS8).
Entonces, por ejemplo, si desea verificar que se está ejecutando en el dispositivo, debe hacerlo
#if TARGET_OS_SIMULATOR
// Simulator-specific code
#else
// Device-specific code
#endif
dependiendo de cuál sea apropiado para su caso de uso.
Otros consejos
Código actualizado:
Se supone que funciona oficialmente.
#if TARGET_IPHONE_SIMULATOR
NSString *hello = @"Hello, iPhone simulator!";
#elif TARGET_OS_IPHONE
NSString *hello = @"Hello, device!";
#else
NSString *hello = @"Hello, unknown target!";
#endif
Publicación original (desde obsoleto)
Este código le dirá si está ejecutando en un simulador.
#ifdef __i386__
NSLog(@"Running in the simulator");
#else
NSLog(@"Running on a device");
#endif
No directiva de preprocesador, pero esto era lo que estaba buscando cuando llegué a esta pregunta;
NSString *model = [[UIDevice currentDevice] model];
if ([model isEqualToString:@"iPhone Simulator"]) {
//device is simulator
}
La mejor manera de hacer esto es:
#if TARGET_IPHONE_SIMULATOR
y no
#ifdef TARGET_IPHONE_SIMULATOR
ya que siempre está definido: 0 o 1
¡HAY UNA MEJOR MANERA AHORA!
A partir de Xcode 9.3 beta 4, puede usar #if targetEnvironment (simulator)
para verificar.
#if targetEnvironment(simulator)
//Your simulator code
#endif
ACTUALIZACIÓN
Xcode 10 y iOS 12 SDK también lo admiten.
En el caso de Swift podemos implementar los siguientes
Podemos crear una estructura que le permite crear datos estructurados
struct Platform {
static let isSimulator: Bool = {
#if arch(i386) || arch(x86_64)
return true
#endif
return false
}()
}
Entonces, si quisiéramos detectar si la aplicación se está creando para un dispositivo o simulador en Swift, entonces.
if Platform.isSimulator {
// Do one thing
}
else {
// Do the other
}
Todas esas respuestas son buenas, pero de alguna manera confunde a los novatos como yo, ya que no aclara la verificación de compilación y la verificación de tiempo de ejecución. El preprocesador es anterior al tiempo de compilación, pero debemos aclararlo
Este artículo de blog muestra Cómo detectar el simulador de iPhone? claramente
Tiempo de ejecución
En primer lugar, discutamos brevemente. UIDevice ya le proporciona información sobre el dispositivo
[[UIDevice currentDevice] model]
le devolverá & # 8220; iPhone Simulator & # 8221; o & # 8220; iPhone & # 8221; según dónde se ejecute la aplicación.
Tiempo de compilación
Sin embargo, lo que quiere es usar el tiempo de compilación definido. ¿Por qué? Porque compila su aplicación estrictamente para que se ejecute dentro del Simulador o en el dispositivo. Apple hace una definición llamada TARGET_IPHONE_SIMULATOR
. Así que veamos el código:
#if TARGET_IPHONE_SIMULATOR
NSLog(@"Running in Simulator - no app store or giro");
#endif
Funciona para Swift 4
y Xcode 9.4.1
Use este código:
#if targetEnvironment(simulator)
// Simulator
#else
// Device
#endif
Las respuestas anteriores están un poco anticuadas. Descubrí que todo lo que necesita hacer es consultar la macro TARGET_IPHONE_SIMULATOR
( no es necesario incluir ningún otro archivo de encabezado [suponiendo que esté codificando para iOS]).
Intenté TARGET_OS_IPHONE
pero me devolvió el mismo valor (1) cuando se ejecutaba en un dispositivo y simulador real, por eso recomiendo usar TARGET_IPHONE_SIMULATOR
.
En rápido:
#if (arch(i386) || arch(x86_64))
...
#endif
De Detectar si la aplicación es siendo construido para dispositivo o simulador en Swift
Tuve el mismo problema, tanto TARGET_IPHONE_SIMULATOR
como TARGET_OS_IPHONE
siempre están definidos y están configurados en 1. La solución de Pete funciona, por supuesto, pero si alguna vez construir sobre otra cosa que no sea Intel (poco probable, pero quién sabe), aquí hay algo que es seguro siempre que el hardware del iPhone no cambie (por lo que su código siempre funcionará para los iphones actualmente disponibles):
#if defined __arm__ || defined __thumb__
#undef TARGET_IPHONE_SIMULATOR
#define TARGET_OS_IPHONE
#else
#define TARGET_IPHONE_SIMULATOR 1
#undef TARGET_OS_IPHONE
#endif
Ponga eso en un lugar conveniente, y luego pretenda que las constantes TARGET_ *
se definieron correctamente.
Para Swift 4.2 / xCode 10
Creé una extensión en UIDevice, por lo que puedo preguntar fácilmente si el simulador se está ejecutando.
// 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
}
}
En mi AppDelegate , por ejemplo, uso este método para decidir si es necesario registrarse para la notificación remota, lo que no es posible para el simulador.
// CHECK FOR REAL DEVICE / OR SIMULATOR
if UIDevice.isSimulator() == false {
// REGISTER FOR SILENT REMOTE NOTIFICATION
application.registerForRemoteNotifications()
}
¿Alguien ha considerado la respuesta proporcionada aquí ?
Supongo que el objetivo-c equivalente sería
+ (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);
}
}
Para incluir todos los tipos de "simuladores"
NSString *model = [[UIDevice currentDevice] model];
if([model rangeOfString:@"Simulator" options:NSCaseInsensitiveSearch].location !=NSNotFound)
{
// we are running in a simulator
}
Con Swift 4.2 (Xcode 10), podemos hacer esto
#if targetEnvironment(simulator)
//simulator code
#else
#warning("Not compiling for simulator")
#endif
Mi respuesta se basa en la respuesta de @Daniel Magnusson y los comentarios de @Nuthatch y @ n.Drake. y lo escribo para ahorrar tiempo a los usuarios rápidos que trabajan en iOS9 y en adelante.
Esto es lo que funcionó para mí:
if UIDevice.currentDevice().name.hasSuffix("Simulator"){
//Code executing on Simulator
} else{
//Code executing on Device
}
/// Devuelve verdadero si es un simulador y no un dispositivo
public static var isSimulator: Bool {
#if (arch(i386) || arch(x86_64)) && os(iOS)
return true
#else
return false
#endif
}
Apple ha agregado soporte para verificar que la aplicación esté dirigida al simulador con lo siguiente:
#if targetEnvironment(simulator)
let DEVICE_IS_SIMULATOR = true
#else
let DEVICE_IS_SIMULATOR = false
#endif
si nada funcionó, intente esto
public struct Platform {
public static var isSimulator: Bool {
return TARGET_OS_SIMULATOR != 0 // Use this line in Xcode 7 or newer
}
}
Esto funcionó mejor para mí
NSString *name = [[UIDevice currentDevice] name];
if ([name isEqualToString:@"iPhone Simulator"]) {
}
En mi opinión, la respuesta (presentada arriba y repetida abajo):
NSString *model = [[UIDevice currentDevice] model];
if ([model isEqualToString:@"iPhone Simulator"]) {
//device is simulator
}
es la mejor respuesta porque obviamente se ejecuta en tiempo de ejecución en lugar de ser una DIRECTIVA DE COMPILACIÓN.