Come posso determinare a livello di codice se la mia app è in esecuzione nel simulatore di iPhone?

StackOverflow https://stackoverflow.com/questions/458304

Domanda

Come afferma la domanda, vorrei principalmente sapere se il mio codice è in esecuzione nel simulatore, ma sarei anche interessato a conoscere la versione specifica di iPhone in esecuzione o in fase di simulazione.

EDIT: ho aggiunto la parola "a livello di codice" al nome della domanda. Il punto della mia domanda è essere in grado di includere / escludere dinamicamente il codice in base alla versione / simulatore in esecuzione, quindi sarei davvero alla ricerca di qualcosa come una direttiva pre-processore che possa fornirmi queste informazioni.

È stato utile?

Soluzione

Già chiesto, ma con un titolo molto diverso.

Quali #define sono impostati da Xcode quando compilazione per iPhone

Ripeterò la mia risposta da lì:

È contenuto nei documenti SDK in " Compilare il codice sorgente in modo condizionale "

La definizione pertinente è TARGET_OS_SIMULATOR, che è definita in /usr/include/TargetConditionals.h all'interno del framework iOS. Nelle versioni precedenti della toolchain, dovevi scrivere:

#include "TargetConditionals.h"

ma questo non è più necessario sull'attuale toolchain (Xcode 6 / iOS8).

Quindi, per esempio, se vuoi controllare che stai funzionando sul dispositivo, dovresti farlo

#if TARGET_OS_SIMULATOR
    // Simulator-specific code
#else
    // Device-specific code
#endif

a seconda di quale è appropriato per il tuo caso d'uso.

Altri suggerimenti

Codice aggiornato:

Si presume che funzioni ufficialmente.

#if TARGET_IPHONE_SIMULATOR
NSString *hello = @"Hello, iPhone simulator!";
#elif TARGET_OS_IPHONE
NSString *hello = @"Hello, device!";
#else
NSString *hello = @"Hello, unknown target!";
#endif

Post originale (dal momento che è obsoleto)

Questo codice ti dirà se stai eseguendo un simulatore.

#ifdef __i386__
NSLog(@"Running in the simulator");
#else
NSLog(@"Running on a device");
#endif

Non direttiva pre-processore, ma questo era quello che stavo cercando quando sono arrivato a questa domanda;

NSString *model = [[UIDevice currentDevice] model];
if ([model isEqualToString:@"iPhone Simulator"]) {
    //device is simulator
}

Il modo migliore per farlo è:

#if TARGET_IPHONE_SIMULATOR

e non

#ifdef TARGET_IPHONE_SIMULATOR

poiché è sempre stato definito: 0 o 1

C'È UN MODO MIGLIORE ORA!

A partire da Xcode 9.3 beta 4 è possibile utilizzare #if targetEnvironment (simulatore) per verificare.

#if targetEnvironment(simulator)
//Your simulator code
#endif

Aggiorna
Xcode 10 e iOS 12 SDK supportano anche questo.

In caso di Swift possiamo implementare quanto segue

Siamo in grado di creare struct che ti consente di creare dati strutturati

struct Platform {
    static let isSimulator: Bool = {
        #if arch(i386) || arch(x86_64)
            return true
        #endif
        return false
    }()
}

Quindi, se volessimo rilevare se l'app è stata costruita per dispositivo o simulatore in Swift, allora.

if Platform.isSimulator {
    // Do one thing
}
else {
    // Do the other
}

Tutte queste risposte sono buone, ma in qualche modo confonde il principiante come me in quanto non chiarisce il controllo di compilazione e il controllo di runtime. Il preprocessore è in anticipo sui tempi di compilazione, ma dovremmo renderlo più chiaro

Questo articolo di blog mostra Come rilevare il simulatore di iPhone? chiaramente

Runtime

Prima di tutto, discutiamo tra poco. UIDevice ti fornisce già informazioni sul dispositivo

[[UIDevice currentDevice] model]

ti restituirà & # 8220; iPhone Simulator & # 8221; o & # 8220; iPhone & # 8221; in base a dove è in esecuzione l'app.

Tempo di compilazione

Comunque ciò che vuoi è usare definisce il tempo di compilazione. Perché? Perché compili la tua app rigorosamente per essere eseguita all'interno del simulatore o sul dispositivo. Apple effettua una definizione chiamata TARGET_IPHONE_SIMULATOR . Quindi diamo un'occhiata al codice:

#if TARGET_IPHONE_SIMULATOR

NSLog(@"Running in Simulator - no app store or giro");

#endif

Funziona con Swift 4 e Xcode 9.4.1

Usa questo codice:

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

Le risposte precedenti sono un po 'datate. Ho scoperto che tutto ciò che devi fare è interrogare la macro TARGET_IPHONE_SIMULATOR ( non è necessario includere altri file di intestazione [supponendo che stai codificando per iOS]).

Ho provato TARGET_OS_IPHONE ma ha restituito lo stesso valore (1) durante l'esecuzione su un dispositivo e un simulatore effettivi, ecco perché consiglio invece di utilizzare TARGET_IPHONE_SIMULATOR

In rapido:

#if (arch(i386) || arch(x86_64))
...            
#endif

Da Rileva se l'app è in fase di creazione per dispositivo o simulatore in Swift

Ho avuto lo stesso problema, sia TARGET_IPHONE_SIMULATOR che TARGET_OS_IPHONE sono sempre definiti e sono impostati su 1. La soluzione di Pete funziona, ovviamente, ma se ti capita mai di basarsi su qualcosa di diverso da Intel (improbabile, ma chissà), ecco qualcosa che è sicuro finché l'hardware dell'iPhone non cambia (quindi il tuo codice funzionerà sempre per gli iPhone attualmente in circolazione):

#if defined __arm__ || defined __thumb__
#undef TARGET_IPHONE_SIMULATOR
#define TARGET_OS_IPHONE
#else
#define TARGET_IPHONE_SIMULATOR 1
#undef TARGET_OS_IPHONE
#endif

Mettilo in un posto comodo, quindi fai finta che le costanti TARGET_ * siano state definite correttamente.

Per Swift 4.2 / xCode 10

Ho creato un'estensione su UIDevice, quindi posso facilmente chiedere se il simulatore è in esecuzione.

// 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
    }
}

Nel mio AppDelegate ad esempio utilizzo questo metodo per decidere se è necessaria la registrazione per la notifica remota, cosa impossibile per il simulatore.

// CHECK FOR REAL DEVICE / OR SIMULATOR
if UIDevice.isSimulator() == false {

    // REGISTER FOR SILENT REMOTE NOTIFICATION
    application.registerForRemoteNotifications()
}

Qualcuno ha considerato la risposta fornita qui ?

Suppongo che l'equivalente in obiettivo c sarebbe

+ (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);
    }
}

Per includere tutti i tipi di " simulatori "

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), possiamo farlo

#if targetEnvironment(simulator)
  //simulator code
#else 
  #warning("Not compiling for simulator")
#endif

La mia risposta si basa sulla risposta di @Daniel Magnusson e sui commenti di @Nuthatch e @ n.Drake. e lo scrivo per risparmiare un po 'di tempo per gli utenti veloci che lavorano su iOS9 e versioni successive.

Questo è ciò che ha funzionato per me:

if UIDevice.currentDevice().name.hasSuffix("Simulator"){
    //Code executing on Simulator
} else{
    //Code executing on Device
}

/// Restituisce vero se il suo simulatore e non un dispositivo

public static var isSimulator: Bool {
    #if (arch(i386) || arch(x86_64)) && os(iOS)
        return true
    #else
        return false
    #endif
}

Apple ha aggiunto il supporto per verificare che l'app sia destinata al simulatore con quanto segue:

#if targetEnvironment(simulator)
let DEVICE_IS_SIMULATOR = true
#else
let DEVICE_IS_SIMULATOR = false
#endif

se non ha funzionato nulla, prova

public struct Platform {

    public static var isSimulator: Bool {
        return TARGET_OS_SIMULATOR != 0 // Use this line in Xcode 7 or newer
    }

}

Questo ha funzionato meglio per me

NSString *name = [[UIDevice currentDevice] name];


if ([name isEqualToString:@"iPhone Simulator"]) {

}

Secondo me, la risposta (presentata sopra e ripetuta sotto):

NSString *model = [[UIDevice currentDevice] model];
if ([model isEqualToString:@"iPhone Simulator"]) {
    //device is simulator
}

è la risposta migliore perché è ovviamente eseguita in RUNTIME anziché essere una DIRETTIVA COMPILE.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top