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 de tiempo de compilación y no están disponibles en tiempo de ejecución.
¿Cómo puedo lograr lo mismo en Swift?
Respuestas:
Actualización 30/01/19
Si bien esta respuesta puede funcionar, la solución recomendada para una comprobación estática (como 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 comprobación estática (por ejemplo, no es un tiempo de ejecución si / no) no puede detectar el simulador directamente, pero puede detectar iOS en una arquitectura de escritorio de la siguiente manera
Después de la versión Swift 4.1
Para más aclaraciones, puede consultar la propuesta de Swift SE-0190
Claramente, esto es falso en un dispositivo, pero devuelve verdadero para el Simulador de iOS, como se especifica en la documentación :
Si está desarrollando un simulador que no sea iOS, simplemente puede variar el
os
parámetro: por ejemploDetecta el simulador de watchOS
Detecta el simulador de tvOS
O, incluso, detectar cualquier simulador
Si, en cambio, está de acuerdo con una verificación de tiempo de ejecución, puede inspeccionar la
TARGET_OS_SIMULATOR
variable (oTARGET_IPHONE_SIMULATOR
en iOS 8 y versiones posteriores), lo cual es cierto en un simulador.Tenga en cuenta que esto es diferente y un poco más limitado que usar un indicador de preprocesador. Por ejemplo, no podrá usarlo en el lugar donde a
if/else
es sintácticamente invá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 verificación dinámica, mientras que es trivial con una verificación estática.
Además, dado que el indicador es reemplazado por a
0
o a1
por el preprocesador rápido, si lo usa directamente en unaif/else
expresión, el compilador generará una advertencia sobre el código inalcanzable.Para evitar esta advertencia, consulte una de las otras respuestas.
fuente
arch(i386) && os(iOS)
.#if targetEnvironment(simulator)
:) ( github.com/apple/swift-evolution/blob/master/proposals/… )ACTUALIZADO PARA SWIFT 4.1. Usar en su
#if targetEnvironment(simulator)
lugar. FuentePara detectar el simulador en Swift, puede usar la configuración de compilación:
Ahora podría usar esta declaración para detectar el simulador:
También podría extender la clase UIDevice:
fuente
xcconfig
archivos usandoOTHER_SWIFT_FLAGS = TARGET_OS_EMBEDDED
yOTHER_SWIFT_FLAGS[sdk=embeddedsimulator*] = TARGET_OS_SIMULATOR
para anular el Simulador.Información 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.
Detecta 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.
Ejemplo de uso:
fuente
public let IS_SIMULATOR = (TARGET_OS_SIMULATOR != 0)
... lo mismo, simplificado. +1 graciasTARGET_OS_SIMULATOR != 0
está en la respuesta . Es la solución dada por Daniel. No es necesario agregarlo nuevamente en una variable libre, ya está allí. Si cree que tenerlo en una estructura es malo y tenerlo en una variable libre es mejor, publique un comentario al respecto o haga su propia respuesta. Gracias.Desde Xcode 9.3
iOS 9+:
Swift 3:
Antes de iOS 9:
C objetivo:
fuente
will never be executed
advertenciaSwift 4
Ahora puede usarlo
targetEnvironment(simulator)
como argumento.Actualizado para Xcode 9.3
fuente
Permítanme aclarar algunas cosas aquí:
TARGET_OS_SIMULATOR
no se establece en el código Swift en muchos casos; es posible que lo haya importado accidentalmente debido a un encabezado de puente, pero esto es frágil y no es compatible. Tampoco es posible en frameworks. Es por eso que algunas personas están confundidas acerca de si esto funciona en Swift.Para realizar comprobaciones dinámicas:
La comprobación
ProcessInfo.processInfo.environment["SIMULATOR_DEVICE_NAME"] != nil
está perfectamente bien.También puede obtener el modelo subyacente que se está simulando al verificar
SIMULATOR_MODEL_IDENTIFIER
qué devolverá cadenas comoiPhone10,3
.Para realizar comprobaciones estáticas:
Xcode 9.2 y anteriores: defina su propio indicador de compilación Swift (como se muestra en otras respuestas).
Xcode 9.3+ usa la nueva condición targetEnvironment:
fuente
targetEnvironment
aterrizó en Xcode 9.3. Necesita una versión más nueva de Xcode.Lo que funciona para mí desde Swift 1.0 es buscar una arquitectura que no sea arm:
fuente
Tiempo de ejecución, pero más simple que la mayoría de las otras soluciones aquí:
Alternativamente, puede llamar a una función auxiliar Objective-C que devuelve un valor booleano que usa la macro del preprocesador (especialmente si ya está mezclando en su proyecto).
Editar: no es la mejor solución, especialmente a partir de Xcode 9.3. Ver la respuesta de HotJard
fuente
== 0
lugar de!= 0
. Usarlo como está escrito arriba, incluso con unelse
bloque después, no produce ninguna advertencia en Swift 4 Xcode Versión 9.2 (9C40b)En sistemas modernos:
Es muy fácil.
fuente
TARGET_IPHONE_SIMULATOR
está en desuso en iOS 9.TARGET_OS_SIMULATOR
es el reemplazo. TambiénTARGET_OS_EMBEDDED
está disponibleDesde TargetConditionals.h :
fuente
Espero que esta extensión sea útil.
Uso:
fuente
En Xcode 7.2 (y anteriores, pero no he probado cuánto antes), puede establecer un indicador de compilación específico de plataforma "-D TARGET_IPHONE_SIMULATOR" para "Any iOS Simulator".
Busque en la configuración de compilación del proyecto en "Compilador Swift - Indicadores del cliente" y luego establezca el indicador en "Otros indicadores Swift". Puede establecer un indicador específico de plataforma haciendo clic en el ícono 'más' cuando pasa el mouse 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) Puede compilar variables que solo se aplican a cada compilación.
Captura de pantalla de configuración de compilación de Xcode
fuente
Todo descrito aquí Darwin.TargetConditionals : https://github.com/apple/swift-corelibs-foundation/blob/master/CoreFoundation/Base.subproj/SwiftRuntime/TargetConditionals.h
TARGET_OS_SIMULATOR - Generated code will run under a simulator
fuente
Usé este código a continuación en Swift 3
fuente
Swift 4:
Actualmente, prefiero usar la clase ProcessInfo para saber si el dispositivo es un simulador y qué tipo de dispositivo está en uso:
Pero, como saben,
simModelCode
no es un código cómodo para comprender de inmediato qué tipo de simulador se lanzó, por lo que, si es necesario, puede intentar ver esta otra respuesta SO para determinar el modelo actual de iPhone / dispositivo y tener un humano más cadena legible.fuente
Aquí hay un ejemplo de Xcode 11 Swift basado en la increíble respuesta de HotJard anterior , esto también agrega un
isDevice
Bool y usa enSIMULATOR_UDID
lugar de nombre. Las asignaciones variables se realizan en cada línea para que pueda examinarlas más fácilmente en el depurador si lo desea.También existe la entrada del diccionario
DTPlatformName
que debe contenersimulator
.fuente
Use este código a continuación:
Trabaja para
Swift 4
yXcode 9.4.1
fuente
Xcode 11, Swift 5
fuente
Además de otras respuestas.
En Objective-c, solo asegúrese de incluir TargetConditionals .
#include <TargetConditionals.h>
antes de usar
TARGET_OS_SIMULATOR
.fuente