Cómo detectar si la aplicación se está creando para dispositivo o simulador en Swift

Resuelto Rafał Sroka asked hace 54 años • 21 respuestas

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?

Rafał Sroka avatar Jan 01 '70 08:01 Rafał Sroka
Aceptado

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 ospará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_SIMULATORvariable (o TARGET_IPHONE_SIMULATORen 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/elsesea 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 0o a 1, si la usa directamente en una if/elseexpresión, el compilador generará una advertencia sobre código inalcanzable.

Para solucionar esta advertencia, consulte una de las otras respuestas.

Gabriele Petronella avatar Jul 21 '2014 16:07 Gabriele Petronella

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ú desplegableLa lista 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
mbelsky avatar May 09 '2016 19:05 mbelsky

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")
}
Daniel avatar May 17 '2015 07:05 Daniel

veloz 4

Ahora puedes usarlo targetEnvironment(simulator)como argumento.

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

Actualizado para Xcode 9.3

JDev avatar Apr 03 '2018 15:04 JDev

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
HotJard avatar Jul 28 '2015 10:07 HotJard