как программно определить, запущено ли мое приложение в симуляторе iphone?

<p>как говорится в вопросе, я бы хотел узнать, работает ли мой код в симуляторе, но также хотел бы узнать, какая конкретная версия iphone запущена или имитируется.</p><p>правка: я добавил слово «программно» к названию вопроса. суть моего вопроса в том, чтобы иметь возможность динамически включать/исключать код в зависимости от того, какая версия/симулятор запущена, поэтому я действительно искал бы что-то вроде директивы препроцессора, которая может предоставить мне эту информацию.</p>

<p>уже спросил, но с совершенно другим названием.</p><p> <a href="https://stackoverflow.com/questions/146986/what-defines-are-setup-by-xcode-when-compiling-for-iphone">что #defines устанавливает xcode при компиляции для iphone</a> </p><p>я повторю свой ответ оттуда:</p><p>он находится в документации sdk в разделе «условная компиляция исходного кода»</p><p>соответствующее определение - target\_os\_simulator, которое определено в /usr/include/targetconditionals.h в рамках ios. в более ранних версиях цепочки инструментов вы должны были написать:</p><pre><code>#include "targetconditionals.h" </code></pre><p>но в текущей (xcode 6/ios8) цепочке инструментов это больше не требуется.</p><p>так, например, если вы хотите проверить, что вы работаете на устройстве, вы должны сделать</p><pre><code>#if target\_os\_simulator // simulator-specific code #else // device-specific code #endif </code></pre><p>в зависимости от того, который подходит для вашего варианта использования.</p>

<h1>обновленный код:</h1><p>это предполагается работать официально.</p><pre><code>#if target\_iphone\_simulator nsstring *hello = @"hello, iphone simulator!"; #elif target\_os\_iphone nsstring *hello = @"hello, device!"; #else nsstring *hello = @"hello, unknown target!"; #endif </code></pre><hr><h1>исходное сообщение<em> (поскольку устарело) </em></h1><p>этот код скажет вам, если вы работаете в симуляторе.</p><pre><code>#ifdef \_\_i386\_\_ nslog(@"running in the simulator"); #else nslog(@"running on a device"); #endif </code></pre>

<p>не директива препроцессора, но именно это я и искал, когда пришел к этому вопросу;</p><pre><code>nsstring *model = [[uidevice currentdevice] model]; if ([model isequaltostring:@"iphone simulator"]) { //device is simulator } </code></pre>

<p>лучший способ сделать это:</p><pre><code>#if target\_iphone\_simulator </code></pre><p>и не</p><pre><code>#ifdef target\_iphone\_simulator </code></pre><p>так как его всегда определяется: 0 или 1</p>

<p><strong> в случае swift мы можем реализовать следующее </strong></p><p>мы можем создать структуру, которая позволяет создавать структурированные данные</p><pre><code>struct platform { static let issimulator: bool = { #if arch(i386) || arch(x86\_64) return true #endif return false }() } </code></pre><p>тогда если мы хотим определить, создается ли приложение для устройства или симулятора в swift, тогда.</p><pre><code>if platform.issimulator { // do one thing } else { // do the other } </code></pre>

<p>там is лучше путь сейчас! </p><p>начиная с xcode 9.3 beta 4, вы можете использовать <code>#if targetenvironment(simulator)</code> для проверки.</p><pre><code>#if targetenvironment(simulator) //your simulator code #endif </code></pre><p><strong>обновление</strong><br> xcode 10 и ios 12 sdk также поддерживают это.</p>

<p>все эти ответы хороши, но это как-то сбивает с толку новичка, такого как я, так как не проясняет проверку компиляции и проверки во время выполнения. препроцессор находится перед временем компиляции, но мы должны сделать его более понятным</p><p>эта статья блога показывает <a href="http://ios.biomsoft.com/2011/09/20/how-to-detect-the-iphone-simulator/">как обнаружить симулятор iphone?</a> ясно </p><p><strong>runtime</strong></p><p>прежде всего, давайте кратко обсудим. uidevice уже предоставляет вам информацию об устройстве</p><pre><code>[[uidevice currentdevice] model] </code></pre><p>вернет вам «iphone simulator» или «iphone» в зависимости от того, где запущено приложение.</p><p><strong>время компиляции</strong></p><p>однако вы хотите использовать определения времени компиляции. зачем? потому что вы компилируете свое приложение строго для запуска внутри симулятора или на устройстве. apple делает определение под названием <code>target\_iphone\_simulator</code>. итак, давайте посмотрим на код:</p><pre><code>#if target\_iphone\_simulator nslog(@"running in simulator - no app store or giro"); #endif </code></pre>

<p>в свифте: </p><pre><code>#if (arch(i386) || arch(x86\_64)) ... #endif </code></pre><p>from <a href="https://stackoverflow.com/questions/24869481/detect-if-app-is-being-built-for-device-or-simulator-in-swift">определить, создается ли приложение для устройства или симулятора в swift</a> </p>

<p>предыдущие ответы немного устарели. я обнаружил, что все, что вам нужно сделать, это запросить макрос <code>target\_iphone\_simulator</code> (<strong> нет необходимости включать другие заголовочные файлы </strong>[при условии, что вы кодируете для ios]).</p><p>я пытался <code>target\_os\_iphone</code>, но он возвращал то же значение (1) при работе на реальном устройстве и симуляторе, поэтому я рекомендую вместо него использовать <code>target\_iphone\_simulator</code>.</p>

<p>у меня была одна и та же проблема, и <code>target\_iphone\_simulator</code>, и <code>target\_os\_iphone</code> всегда определены и установлены на 1. решение пита, конечно, работает, но если вам когда-нибудь удастся использовать что-то отличное от intel (маловероятно, но кто знает), вот что безопасно до тех пор, пока аппаратное обеспечение iphone не изменится (т. е. ваш код всегда будет работать для iphone):</p><pre><code>#if defined \_\_arm\_\_ || defined \_\_thumb\_\_ #undef target\_iphone\_simulator #define target\_os\_iphone #else #define target\_iphone\_simulator 1 #undef target\_os\_iphone #endif </code></pre><p>поместите это где-нибудь удобно, а затем представьте, что константы <code>target\_*</code> были определены правильно.</p>

<p>работает для <code>swift 4</code> и <code>xcode 9.4.1</code></p><p>используйте этот код:</p><pre><code>#if targetenvironment(simulator) // simulator #else // device #endif </code></pre>

<p><strong> для swift 4.2/xcode 10 </strong></p><p>я создал расширение для uidevice, поэтому я могу легко спросить, работает ли симулятор.</p><pre><code>// 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 } } </code></pre><p>например, в моем<strong> appdelegate </strong>я использую этот метод, чтобы решить, необходима ли регистрация для удаленного уведомления, что невозможно для симулятора.</p><pre><code>// check for real device / or simulator if uidevice.issimulator() == false { // register for silent remote notification application.registerforremotenotifications() } </code></pre>

<p>кто-нибудь считал ответ предоставленным <a href="https://github.com/eddyverbruggen/nativescript-secure-storage/blob/70aa5e88691c073312e334c9963c444c3f4d86d5/secure-storage.ios.ts#l12-l24">здесь</a> ?</p><p>я полагаю, что объективный эквивалент с </p><pre><code>+ (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); } } </code></pre>

<p>включить все виды «симуляторов»</p><pre><code>nsstring *model = [[uidevice currentdevice] model]; if([model rangeofstring:@"simulator" options:nscaseinsensitivesearch].location !=nsnotfound) { // we are running in a simulator } </code></pre>

<p>с swift 4.2 (xcode 10) мы можем сделать это</p><pre><code>#if targetenvironment(simulator) //simulator code #else #warning("not compiling for simulator") #endif </code></pre>

<p>/// возвращает true, если его симулятор, а не устройство</p><pre><code>public static var issimulator: bool { #if (arch(i386) || arch(x86\_64)) && os(ios) return true #else return false #endif } </code></pre>

<p><strong> если ничего не получилось, попробуйте это </strong></p><pre><code>public struct platform { public static var issimulator: bool { return target\_os\_simulator != 0 // use this line in xcode 7 or newer } } </code></pre>

<p>apple добавила поддержку для проверки того, что приложение предназначено для симулятора: </p><pre><code>#if targetenvironment(simulator) let device\_is\_simulator = true #else let device\_is\_simulator = false #endif </code></pre>

<p>мой ответ основан на ответе @daniel magnusson и комментариях @nuthatch и @ n.drake. и я пишу это, чтобы сэкономить время для пользователей swift, работающих на ios9 и далее.</p><p>вот что сработало для меня:</p><pre><code>if uidevice.currentdevice().name.hassuffix("simulator"){ //code executing on simulator } else{ //code executing on device } </code></pre>

<p><strong> решение swift 4 </strong></p><pre><code>static let issimulator: bool = { return target\_os\_simulator == 1 }() </code></pre><p><code>target\_os\_simulator</code> находится в файле <code>darwin.targetconditionals.swift</code>.</p>