In Objective-C können wir wissen, ob eine App für ein Gerät oder einen Simulator mit Makros erstellt wird:
#if TARGET_IPHONE_SIMULATOR
// Simulator
#else
// Device
#endif
Dies sind Makros zur Kompilierungszeit, die zur Laufzeit nicht verfügbar sind.
Wie kann ich dasselbe in Swift erreichen? Ich habe den Stack-Überlauf gesucht, habe mir die Dokumente angesehen und kann es nicht herausfinden.
Während diese Antwort möglicherweise funktioniert, ist die empfohlene Lösung für eine statische Überprüfung (von mehreren Apple-Ingenieuren klargestellt), ein benutzerdefiniertes Compiler-Flag für iOS-Simulatoren zu definieren. Ausführliche Anweisungen dazu finden Sie in der Antwort von @ mbelsky .
Wenn Sie eine statische Überprüfung benötigen (z. B. keine Laufzeit, wenn/else), können Sie den Simulator nicht direkt erkennen, aber Sie können iOS auf einer Desktop-Architektur wie folgt erkennen
#if (Arch(i386) || Arch(x86_64)) && os(iOS)
...
#endif
Nach Swift 4.1 version
Neueste Verwendung, jetzt direkt für alle in einer Bedingung, für alle Arten von Simulatoren muss nur eine Bedingung angewendet werden -
#if targetEnvironment(simulator)
// your simulator code
#else
// your real device code
#endif
Zur weiteren Erläuterung können Sie Swift Vorschlag SE-0190überprüfen. _
Für ältere Version -
Natürlich ist dies auf einem Gerät falsch, aber es gibt den Wert für den iOS-Simulator zurück, wie in der Dokumentation angegeben :
Die Build-Konfiguration für Arch (i386) gibt true zurück, wenn der Code für den 32-Bit-iOS-Simulator kompiliert wird.
Wenn Sie für einen anderen Simulator als iOS entwickeln, können Sie einfach den Parameter os
variieren: z.
Erkennen Sie den Simulator watchOS
#if (Arch(i386) || Arch(x86_64)) && os(watchOS)
...
#endif
Erkennen Sie den Simulator tvOS
#if (Arch(i386) || Arch(x86_64)) && os(tvOS)
...
#endif
Oder sogar any Simulator erkennen
#if (Arch(i386) || Arch(x86_64)) && (os(iOS) || os(watchOS) || os(tvOS))
...
#endif
Wenn Sie mit einer Laufzeitprüfung in Ordnung sind, können Sie die TARGET_OS_SIMULATOR
-Variable (oder TARGET_IPHONE_SIMULATOR
in iOS 8 und darunter) überprüfen, die auf einem Simulator wahr ist.
Bitte beachten Sie, dass dies anders und etwas eingeschränkter ist als die Verwendung eines Präprozessor-Flags. Zum Beispiel können Sie es nicht dort einsetzen, wo ein if/else
syntaktisch ungültig ist (z. B. außerhalb von Funktionsbereichen).
Angenommen, Sie möchten verschiedene Importe auf dem Gerät und im Simulator haben. Dies ist bei einer dynamischen Prüfung nicht möglich, bei einer statischen Prüfung dagegen trivial.
#if (Arch(i386) || Arch(x86_64)) && os(iOS)
import Foo
#else
import Bar
#endif
Da das Flag durch den Swift-Präprozessor durch einen 0
oder einen 1
ersetzt wird, gibt der Compiler bei direkter Verwendung in einem if/else
-Ausdruck eine Warnung vor nicht erreichbarem Code aus.
Um diese Warnung zu umgehen, lesen Sie eine der anderen Antworten.
OUTDATED FOR Swift 4.1. Verwenden Sie stattdessen #if targetEnvironment(simulator)
. Source
Um den Simulator in Swift zu erkennen, können Sie die Build-Konfiguration verwenden:
Nun könnten Sie diese Anweisung verwenden, um den Simulator zu erkennen:
#if IOS_SIMULATOR
print("It's an iOS Simulator")
#else
print("It's a device")
#endif
Sie können auch die UIDevice-Klasse erweitern:
extension UIDevice {
var isSimulator: Bool {
#if IOS_SIMULATOR
return true
#else
return false
#endif
}
}
// Example of usage: UIDevice.current.isSimulator
Aktualisierte Info vom 20. Februar 2018
Es sieht so aus, als ob @russbishop eine maßgebliche Antwort hat, die diese Antwort "falsch" macht - obwohl sie lange Zeit zu funktionieren schien.
Ermitteln, ob in Swift eine App für ein Gerät oder einen Simulator erstellt wird
Vorherige Antwort
Basierend auf der Antwort von @ WZW und den Kommentaren von @ Pang erstellte ich eine einfache Utility-Struktur. Diese Lösung vermeidet Warnungen, die von @ WZWs Antwort erzeugt werden.
import Foundation
struct Platform {
static var isSimulator: Bool {
return TARGET_OS_SIMULATOR != 0
}
}
Verwendungsbeispiel:
if Platform.isSimulator {
print("Running on Simulator")
}
Ab Xcode 9.3
#if targetEnvironment(simulator)
Swift unterstützt eine neue Plattformbedingung targetEnvironment mit einer einzelner gültiger Argumentsimulator. Bedingte Kompilierung des Formulars '#if targetEnvironment (Simulator)' kann jetzt verwendet werden, um festzustellen, wann das Build-Ziel ein Simulator ist. Der Swift-Compiler versucht, Erkennen, warnen und die Verwendung von targetEnvironment (Simulator) vorschlagen, wenn Auswerten von Plattformbedingungen, die für den Simulator zu testen scheinen Umgebungen indirekt über die vorhandene os () - und Arch () - Plattform Bedingungen. (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
}
}
Vor iOS 9:
extension UIDevice {
static var isSimulator: Bool {
return UIDevice.currentDevice().model == "iPhone Simulator"
}
}
Ziel c:
@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
Sie können jetzt targetEnvironment(simulator)
als Argument verwenden.
#if targetEnvironment(simulator)
// Simulator
#else
// Device
#endif
Aktualisiert für Xcode 9.3
Lassen Sie mich hier einige Dinge klarstellen:
TARGET_OS_SIMULATOR
ist in vielen Fällen nicht im Swift-Code festgelegt. Sie könnten es aufgrund eines Überbrückungskopfs versehentlich importieren, dies ist jedoch spröde und wird nicht unterstützt. Es ist auch nicht einmal in Frameworks möglich. Deshalb sind einige Leute verwirrt, ob dies in Swift funktioniert.So führen Sie dynamische Prüfungen durch:
ProcessInfo.processInfo.environment["SIMULATOR_DEVICE_NAME"] != nil
zu überprüfen ist vollkommen in Ordnung.
Sie können das zugrundeliegende Modell, das simuliert wird, auch abrufen, indem Sie SIMULATOR_MODEL_IDENTIFIER
überprüfen, wodurch Zeichenfolgen wie iPhone10,3
zurückgegeben werden.
So führen Sie statische Prüfungen durch:
Xcode 9.2 und früher: Definieren Sie Ihr eigenes Swift-Kompilierungsflag (wie in anderen Antworten gezeigt).
Xcode 9.3+ verwendet die neue Bedingung targetEnvironment:
#if targetEnvironment(simulator)
// for sim only
#else
// for device
#endif
Was für mich seit Swift 1.0 funktioniert, sucht nach einer anderen Architektur als arm:
#if Arch(i386) || Arch(x86_64)
//simulator
#else
//device
#endif
Laufzeit, aber einfacher als die meisten anderen Lösungen hier:
if TARGET_OS_SIMULATOR != 0 {
// target is current running in the simulator
}
Alternativ können Sie einfach eine Objective-C-Hilfsfunktion aufrufen, die einen Boolean zurückgibt, der das Präprozessor-Makro verwendet (insbesondere, wenn Sie bereits in Ihrem Projekt gemischt haben).
Edit: Nicht die beste Lösung, besonders seit Xcode 9.3. Siehe HotJards Antwort
In modernen Systemen:
#if targetEnvironment(simulator)
// sim
#else
// device
#endif
Es ist einfach.
TARGET_IPHONE_SIMULATOR
ist in iOS 9 veraltet. TARGET_OS_SIMULATOR
ist der Ersatz. Auch TARGET_OS_EMBEDDED
ist verfügbar.
Von 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 */
In Xcode 7.2 (und früher, aber ich habe nicht getestet, wie viel früher), können Sie ein plattformspezifisches Build-Flag "-D TARGET_IPHONE_SIMULATOR" für "Any iOS Simulator" setzen.
Schauen Sie in den Projekterstellungseinstellungen unter "Swift-Compiler - Kundenflags" nach und setzen Sie das Flag in "Andere Swift-Flags". Sie können ein plattformspezifisches Flag setzen, indem Sie auf das Plus-Symbol klicken, wenn Sie mit der Maus über eine Build-Konfiguration fahren.
Es gibt einige Vorteile, wenn Sie dies auf diese Weise tun: 1) Sie können denselben bedingten Test ("#if TARGET_IPHONE_SIMULATOR") in Ihrem Swift- und Objective-C-Code verwenden. 2) Sie können Variablen kompilieren, die nur für jeden Build gelten.
Alle hier beschriebenen 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
Ich habe diesen Code in Swift 3 verwendet
if TARGET_IPHONE_SIMULATOR == 1 {
//simulator
} else {
//device
}
Derzeit ziehe ich es vor, die Klasse ProcessInfo zu verwenden, um zu wissen, ob das Gerät ein Simulator ist und welche Art von Gerät verwendet wird:
if let simModelCode = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] {
print("yes is a simulator :\(simModelCode)")
}
Wie Sie wissen, ist simModelCode
kein bequemer Code, um sofort zu verstehen, welche Art von Simulator gestartet wurde. Wenn Sie also brauchen, können Sie versuchen, mit diesem anderen SO answer das aktuelle iPhone zu ermitteln/Gerätemodell und eine besser lesbare Zeichenfolge.
Ich hoffe, diese Erweiterung ist praktisch
extension UIDevice {
static var isSimulator: Bool = {
var isSimulator = false
#if targetEnvironment(simulator)
isSimulator = true
#endif
return isSimulator
}()
}
Verwendungszweck:
if UIDevice.isSimulator {
print("running on simulator")
}
Verwenden Sie den folgenden Code:
#if targetEnvironment(simulator)
// Simulator
#else
// Device
#endif
Funktioniert für Swift 4
und Xcode 9.4.1