ser perfil development developer desarrollador cuenta como apple app ios swift

ios - perfil - Detectar si la aplicación se está construyendo para un dispositivo o simulador en Swift



ios app development (15)

Actualización 14/09/17

Si bien esta respuesta puede funcionar, la solución recomendada para una verificación estática (según lo aclararon varios ingenieros de Apple) es definir un indicador de compilador personalizado dirigido a los 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 / else) no puede detectar el simulador directamente, pero puede detectar iOS en una arquitectura de escritorio como la siguiente

#if (arch(i386) || arch(x86_64)) && os(iOS) ... #endif

Claramente, esto es falso en un dispositivo, pero se vuelve verdadero para el simulador de iOS, como se especifica en la documentation :

La configuración de compilación de arch (i386) devuelve true cuando el código se compila para el simulador de iOS de 32 bits.

Si está desarrollando para un simulador que no sea iOS, simplemente puede variar el parámetro os : 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 de tiempo de ejecución, puede inspeccionar la variable TARGET_OS_SIMULATOR (o TARGET_IPHONE_SIMULATOR en iOS 8 y más abajo), lo cual es cierto en un simulador.

Tenga en cuenta que esto es diferente y ligeramente más limitado que el uso de un indicador de preprocesador. Por ejemplo, no podrá usarlo en el lugar donde un if/else es sintácticamente no válido (por ejemplo, fuera de los ámbitos de funciones).

Digamos, por ejemplo, que desea tener diferentes importaciones en el dispositivo y en el simulador. Esto es imposible con una comprobación dinámica, mientras que es trivial con una comprobación estática.

#if (arch(i386) || arch(x86_64)) && os(iOS) import Foo #else import Bar #endif

Además, como el preprocesador swift reemplaza el indicador con un 0 o un 1 , si lo usa directamente en una expresión if/else , el compilador emitirá una advertencia sobre el código inaccesible.

Para evitar esta advertencia, vea una de las otras respuestas.

En Objective-C podemos saber si una aplicación se está construyendo para un dispositivo o simulador usando macros:

#if TARGET_IPHONE_SIMULATOR // Simulator #else // Device #endif

Estas son macros de tiempo de compilación y no están disponibles en tiempo de ejecución.

¿Cómo puedo lograr lo mismo en Swift? Busqué en el desbordamiento de pila, eché un vistazo a los documentos y no pude resolverlo.


Swift 4

Ahora puede usar targetEnvironment(simulator) como argumento.

#if targetEnvironment(simulator) // Simulator #else // Device #endif

Actualizado para Xcode 9.3


Swift 4:

Actualmente, prefiero usar la clase ProcessInfo para saber si el dispositivo es un simulador y qué tipo de dispositivo está en uso:

if let simModelCode = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] { print("yes is a simulator :/(simModelCode)") }

Pero, como saben, simModelCode no es un código cómodo para entender inmediatamente qué tipo de simulador se lanzó, por lo que, si lo necesita, puede intentar ver esta otra answer SO para determinar el modelo actual de iPhone / dispositivo y tener una cadena legible humana.


En Xcode 7.2 (y anteriormente, pero no he probado cuánto antes), puede establecer un indicador de compilación específico de la plataforma "-D TARGET_IPHONE_SIMULATOR" para "Cualquier simulador de iOS".

Busque en la configuración de compilación del proyecto en "Compilador de Swift - Banderas del cliente" y luego configure la bandera en "Otras Banderas de Swift". Puede establecer una bandera específica de la plataforma haciendo clic en el icono ''más'' cuando se desplaza sobre una configuración de compilación.

Hay un par de ventajas de hacerlo de esta manera: 1) Puede usar la misma prueba condicional ("#if TARGET_IPHONE_SIMULATOR") en su código Swift y Objective-C. 2) Puedes compilar variables que solo se aplican a cada compilación.

Captura de pantalla de configuración de construcción de Xcode


En los sistemas modernos:

#if targetEnvironment(simulator) // sim #else // device #endif

Es fácil.


Lo que me funciona desde Swift 1.0 es buscar una arquitectura que no sea arm:

#if arch(i386) || arch(x86_64) //simulator #else //device #endif


Permítanme aclarar algunas cosas aquí:

  1. TARGET_OS_SIMULATOR no está configurado en código Swift en muchos casos; es posible que lo esté importando accidentalmente debido a un encabezado puente, pero esto es frágil y no es compatible. Tampoco es posible incluso en marcos. Es por esto que algunas personas están confundidas acerca de si esto funciona en Swift.
  2. Recomiendo encarecidamente no usar la arquitectura como sustituto del simulador.

Para realizar verificaciones dinámicas:

Verificando ProcessInfo.processInfo.environment["SIMULATOR_DEVICE_NAME"] != nil está perfectamente bien.

También puede obtener el modelo subyacente que se está simulando marcando SIMULATOR_MODEL_IDENTIFIER que devolverá cadenas como iPhone10,3 .

Para realizar verificaciones estáticas:

Xcode 9.2 y anteriores: define tu propia bandera de compilación Swift (como se muestra en otras respuestas).

Xcode 9.3+ usa la nueva condición targetEnvironment:

#if targetEnvironment(simulator) // for sim only #else // for device #endif


Tiempo de ejecución, pero más simple que la mayoría de las otras soluciones aquí:

if TARGET_OS_SIMULATOR != 0 { // target is current running in the simulator }

Alternativamente, puede simplemente llamar a una función auxiliar de Objective-C que devuelve un valor booleano que usa la macro del preprocesador (especialmente si ya está mezclando en su proyecto).

Edición: No es la mejor solución, especialmente a partir de Xcode 9.3. Ver la respuesta de HotJard.



Utilicé este código debajo de Swift 3

if TARGET_IPHONE_SIMULATOR == 1 { //simulator } else { //device }


Utilice este código a continuación:

#if targetEnvironment(simulator) // Simulator #else // Device #endif

Trabaja para Swift 4 y Xcode 9.4.1


TARGET_IPHONE_SIMULATOR está en desuso en iOS 9. TARGET_OS_SIMULATOR es el reemplazo. También está disponible TARGET_OS_EMBEDDED .

Desde TargetConditionals.h :

#if defined(__GNUC__) && ( defined(__APPLE_CPP__) || defined(__APPLE_CC__) || defined(__MACOS_CLASSIC__) ) . . . #define TARGET_OS_SIMULATOR 0 #define TARGET_OS_EMBEDDED 1 #define TARGET_IPHONE_SIMULATOR TARGET_OS_SIMULATOR /* deprecated */ #define TARGET_OS_NANO TARGET_OS_WATCH /* deprecated */


Desde Xcode 9.3

#if targetEnvironment(simulator)

Swift admite una nueva condición de plataforma targetEnvironment con un único simulador de argumentos válido. La compilación condicional de la forma ''#if targetEnvironment (simulador)'' puede usarse ahora para detectar cuándo el objetivo de construcción es un simulador. El compilador Swift intentará detectar, advertir y sugerir el uso de targetEnvironment (simulador) al evaluar las condiciones de la plataforma que parecen estar probando los entornos del simulador de manera indirecta, a través de las condiciones existentes de la plataforma os () y arch (). (SE-0190)

iOS 9+:

extension UIDevice { static var isSimulator: Bool { return NSProcessInfo.processInfo().environment["SIMULATOR_DEVICE_NAME"] != nil } }

Swift 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


Info actualizada al 20 de febrero de 2018

Parece que @russbishop tiene una respuesta autorizada que hace que esta respuesta sea "incorrecta", a pesar de que pareció funcionar durante mucho tiempo.

Detectar si la aplicación se está construyendo para un 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 } }

Ejemplo de uso:

if Platform.isSimulator { print("Running on Simulator") }


UTILIZADO PARA SWIFT 4.1. Use #if targetEnvironment(simulator) lugar. github.com/apple/swift-evolution/blob/master/proposals/…

Para detectar 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 simulador de iOS SDK en este menú desplegable

Ahora puedes 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