Cómo detectar si la aplicación se está creando para dispositivo o simulador en Swift
En Objective-C podemos saber si se está creando una aplicación para dispositivo o simulador usando macros:
#if TARGET_IPHONE_SIMULATOR
// Simulator
#else
// Device
#endif
Estas son macros en tiempo de compilación y no están disponibles en tiempo de ejecución.
¿Cómo puedo lograr lo mismo en Swift?
Actualización 30/01/19
Si bien esta respuesta puede funcionar, la solución recomendada para una verificación estática (como lo aclararon varios ingenieros de Apple) es definir un indicador de compilador personalizado dirigido a simuladores de iOS. Para obtener instrucciones detalladas sobre cómo hacerlo, consulte la respuesta de @mbelsky .
Respuesta original
Si necesita una verificación estática (por ejemplo, no un tiempo de ejecución si/de lo contrario), no puede detectar el simulador directamente, pero puede detectar iOS en una arquitectura de escritorio como se muestra a continuación.
#if (arch(i386) || arch(x86_64)) && os(iOS)
...
#endif
Después de la versión Swift 4.1
El último uso, ahora directamente para todo en una sola condición, para todos los tipos de simuladores es necesario aplicar solo una condición:
#if targetEnvironment(simulator)
// your simulator code
#else
// your real device code
#endif
Para más aclaraciones, puede consultar la propuesta Swift SE-0190.
Para la versión anterior -
Claramente, esto es falso en un dispositivo, pero devuelve verdadero para el Simulador de iOS, como se especifica en la documentación :
La configuración de compilación arch(i386) devuelve verdadero cuando se compila el código para el simulador de iOS de 32 bits.
Si está desarrollando para un simulador que no sea iOS, simplemente puede variar el os
parámetro: por ejemplo
Detectar el simulador de watchOS
#if (arch(i386) || arch(x86_64)) && os(watchOS)
...
#endif
Detectar el simulador de tvOS
#if (arch(i386) || arch(x86_64)) && os(tvOS)
...
#endif
O, incluso, detectar cualquier simulador
#if (arch(i386) || arch(x86_64)) && (os(iOS) || os(watchOS) || os(tvOS))
...
#endif
Si, en cambio, está de acuerdo con una verificación del tiempo de ejecución, puede inspeccionar la TARGET_OS_SIMULATOR
variable (o TARGET_IPHONE_SIMULATOR
en iOS 8 y versiones anteriores), lo cual es verdadero en un simulador.
Tenga en cuenta que esto es diferente y un poco más limitado que usar una bandera de preprocesador. Por ejemplo, no podrá usarlo en lugares donde a no if/else
sea sintácticamente inválido (por ejemplo, fuera del alcance de las funciones).
Digamos, por ejemplo, que desea tener importaciones diferentes en el dispositivo y en el simulador. Esto es imposible con una verificación dinámica, mientras que es trivial con una verificación estática.
#if (arch(i386) || arch(x86_64)) && os(iOS)
import Foo
#else
import Bar
#endif
Además, dado que el preprocesador Swift reemplaza la bandera con a 0
o a 1
, si la usa directamente en una if/else
expresión, el compilador generará una advertencia sobre código inalcanzable.
Para solucionar esta advertencia, consulte una de las otras respuestas.
ACTUALIZADO PARA SWIFT 4.1. Úselo #if targetEnvironment(simulator)
en su lugar. Fuente
Para detectar el simulador en Swift puedes usar la configuración de compilación:
- Defina esta configuración -D IOS_SIMULATOR en Swift Compiler - Banderas personalizadas > Otras banderas Swift
- Seleccione Cualquier SDK de simulador de iOS en este menú desplegable
Ahora podrías usar esta declaración para detectar el simulador:
#if IOS_SIMULATOR
print("It's an iOS Simulator")
#else
print("It's a device")
#endif
También puedes extender la clase UIDevice:
extension UIDevice {
var isSimulator: Bool {
#if IOS_SIMULATOR
return true
#else
return false
#endif
}
}
// Example of usage: UIDevice.current.isSimulator
Información actualizada al 20 de febrero de 2018
Parece que @russbishop tiene una respuesta autorizada que hace que esta respuesta sea "incorrecta", aunque pareció funcionar durante mucho tiempo.
Detectar si la aplicación se está creando para dispositivo o simulador en Swift
Respuesta anterior
Basado en la respuesta de @WZW y los comentarios de @Pang, creé una estructura de utilidad simple. Esta solución evita la advertencia producida por la respuesta de @WZW.
import Foundation
struct Platform {
static var isSimulator: Bool {
return TARGET_OS_SIMULATOR != 0
}
}
Uso de ejemplo:
if Platform.isSimulator {
print("Running on Simulator")
}
veloz 4
Ahora puedes usarlo targetEnvironment(simulator)
como argumento.
#if targetEnvironment(simulator)
// Simulator
#else
// Device
#endif
Actualizado para Xcode 9.3
Desde Xcode 9.3
#if targetEnvironment(simulator)
Swift admite una nueva condición de plataforma targetEnvironment con un único simulador de argumento válido. La compilación condicional del formulario '#if targetEnvironment(simulator)' ahora se puede utilizar para detectar cuándo el objetivo de compilación es un simulador. El compilador Swift intentará detectar, advertir y sugerir el uso de targetEnvironment(simulator) al evaluar las condiciones de la plataforma que parecen estar probando entornos de simulador indirectamente, a través de las condiciones de plataforma os() y arch() existentes. (SE-0190)
iOS 9+:
extension UIDevice {
static var isSimulator: Bool {
return NSProcessInfo.processInfo().environment["SIMULATOR_DEVICE_NAME"] != nil
}
}
Rápido 3:
extension UIDevice {
static var isSimulator: Bool {
return ProcessInfo.processInfo.environment["SIMULATOR_DEVICE_NAME"] != nil
}
}
Antes de iOS 9:
extension UIDevice {
static var isSimulator: Bool {
return UIDevice.currentDevice().model == "iPhone Simulator"
}
}
C objetivo:
@interface UIDevice (Additions)
- (BOOL)isSimulator;
@end
@implementation UIDevice (Additions)
- (BOOL)isSimulator {
if([[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){9, 0, 0}]) {
return [NSProcessInfo processInfo].environment[@"SIMULATOR_DEVICE_NAME"] != nil;
} else {
return [[self model] isEqualToString:@"iPhone Simulator"];
}
}
@end