Comme le dit la question, j'aimerais principalement savoir si mon code est en cours d'exécution dans le simulateur, mais j'aimerais également connaître la version spécifique de l'iPhone en cours d'exécution ou en cours de simulation.
EDIT: J'ai ajouté le mot «par programme» au nom de la question. Le but de ma question est de pouvoir inclure et exclure du code de manière dynamique en fonction de la version/du simulateur en cours d'exécution. Je chercherais donc vraiment une directive du préprocesseur capable de me fournir cette information.
Déjà demandé, mais avec un titre très différent.
Quelles sont les définitions définies par Xcode lors de la compilation pour iPhone
Je vais répéter ma réponse à partir de là:
C'est dans la documentation du SDK sous "Compiler le code source de façon conditionnelle"
La définition pertinente est TARGET_OS_SIMULATOR, définie dans /usr/include/TargetConditionals.h dans la structure iOS. Sur les versions précédentes de la chaîne d’outils, vous deviez écrire:
#include "TargetConditionals.h"
mais ce n'est plus nécessaire dans la chaîne d'outils actuelle (Xcode 6/iOS8).
Ainsi, par exemple, si vous voulez vérifier que vous utilisez le périphérique, vous devriez faire
#if TARGET_OS_SIMULATOR
// Simulator-specific code
#else
// Device-specific code
#endif
en fonction de ce qui convient à votre cas d'utilisation.
Ceci est censé fonctionner officiellement.
#if TARGET_IPHONE_SIMULATOR
NSString *hello = @"Hello, iPhone simulator!";
#Elif TARGET_OS_IPHONE
NSString *hello = @"Hello, device!";
#else
NSString *hello = @"Hello, unknown target!";
#endif
Ce code vous dira si vous utilisez un simulateur.
#ifdef __i386__
NSLog(@"Running in the simulator");
#else
NSLog(@"Running on a device");
#endif
Pas de directive du pré-processeur, mais c’était ce que je recherchais lorsque j’en suis venu à cette question;
NSString *model = [[UIDevice currentDevice] model];
if ([model isEqualToString:@"iPhone Simulator"]) {
//device is simulator
}
La meilleure façon de faire est:
#if TARGET_IPHONE_SIMULATOR
et pas
#ifdef TARGET_IPHONE_SIMULATOR
depuis toujours défini: 0 ou 1
En cas de Swift, nous pouvons mettre en œuvre ce qui suit
Nous pouvons créer une structure qui vous permet de créer une donnée structurée
struct Platform {
static let isSimulator: Bool = {
#if Arch(i386) || Arch(x86_64)
return true
#endif
return false
}()
}
Ensuite, si nous voulions détecter si une application est en cours de construction pour un appareil ou un simulateur dans Swift, alors.
if Platform.isSimulator {
// Do one thing
}
else {
// Do the other
}
IL IS UNE MEILLEURE FAÇON MAINTENANT!
A partir de Xcode 9.3 beta 4, vous pouvez utiliser #if targetEnvironment(simulator)
pour vérifier.
#if targetEnvironment(simulator)
//Your simulator code
#endif
METTRE À JOUR
Xcode 10 et iOS 12 SDK le supporte également.
Toutes ces réponses sont bonnes, mais cela confond un débutant comme moi, car cela ne clarifie pas les vérifications de compilation et d’exécution. Les préprocesseurs sont avant la compilation, mais nous devrions le préciser.
Cet article de blog montre Comment détecter le simulateur iPhone? clairement
Runtime
Tout d’abord, discutons brièvement. UIDevice vous fournit déjà des informations sur le périphérique
[[UIDevice currentDevice] model]
vous retournera «iPhone Simulator» ou «iPhone» en fonction de l'emplacement de l'application.
Temps de compilation
Cependant, ce que vous voulez, c'est utiliser le temps de compilation défini. Pourquoi? Parce que vous compilez votre application uniquement pour qu'elle soit exécutée à l'intérieur du simulateur ou sur le périphérique. Apple crée une définition appelée TARGET_IPHONE_SIMULATOR
. Alors regardons le code:
#if TARGET_IPHONE_SIMULATOR
NSLog(@"Running in Simulator - no app store or giro");
#endif
En rapide:
#if (Arch(i386) || Arch(x86_64))
...
#endif
De Détecte si une application est en cours de création pour un appareil ou un simulateur dans Swift
Les réponses précédentes sont un peu datées. J'ai constaté que tout ce que vous avez à faire est d'interroger la macro TARGET_IPHONE_SIMULATOR
( inutile d'inclure d'autres fichiers d'en-tête [en supposant que vous codez pour iOS]).
J'ai essayé TARGET_OS_IPHONE
mais il a retourné la même valeur (1) lors de l'exécution sur un appareil et un simulateur réels, c'est pourquoi je recommande d'utiliser plutôt TARGET_IPHONE_SIMULATOR
.
J'ai eu le même problème, à la fois TARGET_IPHONE_SIMULATOR
et TARGET_OS_IPHONE
sont toujours définis, et sont définis à 1. La solution de Pete fonctionne, bien sûr, mais si vous vous basez sur autre chose qu'Intel (improbable, mais qui sait), voici quelque chose qui est sûr tant que le matériel iphone ne change pas (votre code fonctionnera donc toujours pour les iphones actuellement disponibles):
#if defined __arm__ || defined __thumb__
#undef TARGET_IPHONE_SIMULATOR
#define TARGET_OS_IPHONE
#else
#define TARGET_IPHONE_SIMULATOR 1
#undef TARGET_OS_IPHONE
#endif
Mettez cela à un endroit pratique, puis supposez que les constantes TARGET_*
ont été définies correctement.
Fonctionne pour Swift 4
et Xcode 9.4.1
Utilisez ce code:
#if targetEnvironment(simulator)
// Simulator
#else
// Device
#endif
Pour Swift 4.2/xCode 10
J'ai créé une extension sur UIDevice afin de pouvoir facilement demander si le simulateur est en cours d'exécution.
// 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
}
}
Dans mon AppDelegate par exemple, j'utilise cette méthode pour décider si l'enregistrement pour la notification à distance est nécessaire, ce qui n'est pas possible pour le simulateur.
// CHECK FOR REAL DEVICE / OR SIMULATOR
if UIDevice.isSimulator() == false {
// REGISTER FOR SILENT REMOTE NOTIFICATION
application.registerForRemoteNotifications()
}
Quelqu'un a-t-il envisagé de répondre ici ?
Je suppose que l'équivalent objectif-c serait
+ (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);
}
}
Pour inclure tous les types de "simulateurs"
NSString *model = [[UIDevice currentDevice] model];
if([model rangeOfString:@"Simulator" options:NSCaseInsensitiveSearch].location !=NSNotFound)
{
// we are running in a simulator
}
Avec Swift 4.2 (Xcode 10), nous pouvons le faire
#if targetEnvironment(simulator)
//simulator code
#else
#warning("Not compiling for simulator")
#endif
/// Renvoie true si son simulateur et non un périphérique
public static var isSimulator: Bool {
#if (Arch(i386) || Arch(x86_64)) && os(iOS)
return true
#else
return false
#endif
}
si rien n'a fonctionné, essayez ceci
public struct Platform {
public static var isSimulator: Bool {
return TARGET_OS_SIMULATOR != 0 // Use this line in Xcode 7 or newer
}
}
Apple a ajouté un support pour vérifier que l'application est ciblée pour le simulateur avec les éléments suivants:
#if targetEnvironment(simulator)
let DEVICE_IS_SIMULATOR = true
#else
let DEVICE_IS_SIMULATOR = false
#endif
Ma réponse est basée sur la réponse de @Daniel Magnusson et les commentaires de @Nuthatch et de @ n.Drake. et je l’écris pour gagner du temps pour les utilisateurs de Swift travaillant sur iOS9 et les versions ultérieures.
C'est ce qui a fonctionné pour moi:
if UIDevice.currentDevice().name.hasSuffix("Simulator"){
//Code executing on Simulator
} else{
//Code executing on Device
}
Solution Swift 4
static let isSimulator: Bool = {
return TARGET_OS_SIMULATOR == 1
}()
TARGET_OS_SIMULATOR
est situé dans le fichier Darwin.TargetConditionals.Swift
.