Определить, если приложение создается для устройства или симулятора в Swift
в Objective-C мы можем узнать, создается ли приложение для устройства или симулятора с помощью макросов:
#if TARGET_IPHONE_SIMULATOR
// Simulator
#else
// Device
#endif
это макросы времени компиляции и недоступны во время выполнения.
как я могу достичь того же в Swift? Я искал переполнение стека, заглянул в документы и не могу понять это.
15 ответов:
обновление 14/09/17
хотя этот ответ может работать, рекомендуемое решение для статической проверки (как пояснили несколько инженеров Apple) заключается в определении пользовательского флага компилятора, предназначенного для симуляторов iOS. Для получения подробных инструкций о том, как это сделать, см. @mbelsky это.
оригинальный ответ
Если вам нужна статическая проверка (например, не во время выполнения if / else), вы не можете обнаружить симулятор напрямую, но вы можете обнаружить iOS на рабочем столе архитектура, как следует
#if (arch(i386) || arch(x86_64)) && os(iOS) ... #endifочевидно, что это ложь на устройстве, но она возвращает true для симулятора iOS, как указано в документация:
конфигурация сборки arch(i386) возвращает true при компиляции кода для 32–разрядного симулятора iOS.
если вы разрабатываете для симулятора, отличного от iOS, вы можете просто изменить
обновленная информация по состоянию на 20 февраля 2018 года
похоже, что у @russbishop есть авторитетный ответ, который делает этот ответ "неправильным", хотя он, похоже, работал в течение длительного времени.
определить, если приложение строится для устройства или симулятора в Swift
Предыдущий Ответ
основываясь на ответе @WZW и комментариях @Pang, я создал простую структуру утилиты. Это решение позволяет избежать предупреждения произведено ответом @WZW.
import Foundation struct Platform { static var isSimulator: Bool { return TARGET_OS_SIMULATOR != 0 } }пример использования:
if Platform.isSimulator { print("Running on Simulator") }
УСТАРЕЛ ДЛЯ SWIFT 4.1. использовать
#if targetEnvironment(simulator)вместо. источникдля обнаружения симулятора в Swift вы можете использовать конфигурацию сборки:
- определите эта конфигурация - D IOS_SIMULATOR на Компилятор SWIFT - Пользовательских Флагов > Прочие Флаги Свифт
- выберите любой iOS симулятор SDK в выпадающем
![]()
Теперь вы можете использовать этот заявление для обнаружения тренажера:
#if IOS_SIMULATOR print("It's an iOS Simulator") #else print("It's a device") #endifтакже вы можете расширить класс UIDevice:
extension UIDevice { var isSimulator: Bool { #if IOS_SIMULATOR return true #else return false #endif } } // Example of usage: UIDevice.current.isSimulator
От Xcode 9.3
#if targetEnvironment(simulator)Swift поддерживает новое условие платформы targetEnvironment с a один допустимый аргумент симулятор. Условная компиляция формы "#if targetEnvironment (simulator) " теперь можно использовать для определения того, когда цель сборки является симулятором. Компилятор Swift попытается обнаружьте, предупредите, и предложите пользу targetEnvironment (имитатора) когда оценка условий платформы, которые, по-видимому, тестируются для симулятора среды косвенно, через существующую платформу os () и arch () условия. (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 } }перед iOS 9:
extension UIDevice { static var isSimulator: Bool { return UIDevice.currentDevice().model == "iPhone Simulator" } }Цель-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
Swift 4
теперь вы можете использовать
targetEnvironment(simulator)в качестве аргумента.#if targetEnvironment(simulator) // Simulator #else // Device #endifобновлено для Xcode 9.3
позвольте мне прояснить некоторые вещи здесь:
TARGET_OS_SIMULATORво многих случаях не устанавливается в Swift-коде; вы можете случайно получить его импортированный из-за заголовка моста, но это хрупко и не поддерживается. Это также не возможно даже в рамках. Вот почему некоторые люди путают о том, работает ли это в Swift.- я настоятельно рекомендую не использовать архитектуру в качестве замены симулятора.
для выполнения динамических чеки:
проверка
ProcessInfo.processInfo.environment["SIMULATOR_DEVICE_NAME"] != nilэто прекрасно.вы также можете получить базовую модель моделируется путем проверки
SIMULATOR_MODEL_IDENTIFIER, который будет возвращать строки, какiPhone10,3.для выполнения статических проверок:
Xcode 9.2 & earlier: определите свой собственный флаг компиляции Swift (как показано в других ответах).
Xcode 9.3 + используйте новое условие targetEnvironment:
#if targetEnvironment(simulator) // for sim only #else // for device #endif
что работает для меня, так как Swift 1.0 проверяет архитектуру, отличную от arm:
#if arch(i386) || arch(x86_64) //simulator #else //device #endif
во время выполнения, но проще, чем большинство других решений здесь:
if TARGET_OS_SIMULATOR != 0 { // target is current running in the simulator }кроме того, вы можете просто вызвать вспомогательную функцию Objective-C, которая возвращает логическое значение, которое использует макрос препроцессора (особенно если вы уже смешиваете в своем проекте).
Edit: не лучшее решение, особенно с Xcode 9.3. Смотрите ответ Хотджарда
в современных системах:
#if targetEnvironment(simulator) // sim #else // device #endifэто очень просто.
TARGET_IPHONE_SIMULATORявляется устаревшим в iOS 9.TARGET_OS_SIMULATORзамена. ТакжеTARGET_OS_EMBEDDEDдоступно.С 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 */
в Xcode 7.2 (и ранее, но я не проверял, насколько раньше) вы можете установить флаг сборки для конкретной платформы "-D TARGET_IPHONE_SIMULATOR" для "любого симулятора iOS".
посмотрите в настройках сборки проекта в разделе "Swift Compiler-Customer Flags", а затем установите флаг в разделе"другие флаги Swift". Вы можете установить флаг конкретной платформы, нажав на значок "плюс" при наведении указателя мыши на конфигурацию сборки.
есть несколько преимуществ сделать это таким образом: 1) Вы можно использовать один и тот же условный тест ("#if TARGET_IPHONE_SIMULATOR") в коде Swift и Objective-C. 2) Вы можете скомпилировать переменные, которые применяются только к каждой сборке.
все описано здесь Дарвин.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
Swift 4:
В настоящее время я предпочитаю использовать ProcessInfo класс, чтобы узнать, является ли устройство симулятором и какое устройство используется:
if let simModelCode = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] { print("yes is a simulator :\(simModelCode)") }но, как вы знаете,
simModelCodeэто не удобный код, чтобы сразу понять, какой тип симулятора был запущен, поэтому, если вам нужно, вы можете попробовать увидеть этот другой SO ответ чтобы определить текущую модель iPhone / устройства и иметь более удобочитаемую строку.
используйте этот код ниже:
#if targetEnvironment(simulator) // Simulator #else // Device #endifработает
Swift 4иXcode 9.4.1

Comments