यदि मेरा ऐप iPhone सिम्युलेटर में चल रहा है, तो मैं प्रोग्रामेटिक रूप से कैसे निर्धारित कर सकता हूं?


270

जैसा कि प्रश्न में कहा गया है, मैं मुख्य रूप से यह जानना चाहूंगा कि सिम्युलेटर में मेरा कोड चल रहा है या नहीं, लेकिन विशिष्ट iphone संस्करण को जानने में रुचि होगी जो चल रहा है या अनुकरण किया जा रहा है।

EDIT: मैंने प्रश्न नाम में 'प्रोग्रामेटिकली' शब्द जोड़ा है। मेरे प्रश्न का बिंदु डायनामिक रूप से शामिल होना / कोड को अलग करना है, जिसके आधार पर संस्करण / सिम्युलेटर चल रहा है, इसलिए मैं वास्तव में एक पूर्व-प्रोसेसर निर्देश की तरह कुछ खोज रहा हूं जो मुझे यह जानकारी प्रदान कर सकता है।


मुझे यकीन नहीं है कि एक पूर्व-प्रोसेसर निर्देश गतिशील है (हालांकि यह वही हो सकता है जो आप वैसे भी देख रहे थे)। निर्देश का मतलब है कि आप वास्तव में जानते थे, जब आपने इसे बनाया था, जहां यह चल रहा था।
वाइजऑल्डडक

जवाबों:


356

पहले से ही पूछा, लेकिन बहुत अलग शीर्षक के साथ।

IPhone के लिए संकलन करते समय Xcode द्वारा क्या #defines स्थापित किए जाते हैं

मैं वहां से अपना उत्तर दोहराऊंगा:

यह एसडीके डॉक्स में "संकलित स्रोत कोड सशर्त रूप से" के तहत है

प्रासंगिक परिभाषा TARGET_OS_SIMULATOR है, जिसे /usr/include/TargetConditionals.h में iOS ढांचे के भीतर परिभाषित किया गया है। टूलचैन के पुराने संस्करणों पर, आपको लिखना था:

#include "TargetConditionals.h"

लेकिन यह वर्तमान (Xcode 6 / iOS8) टूलचैन पर आवश्यक नहीं है।

इसलिए, उदाहरण के लिए, यदि आप जांचना चाहते हैं कि आप डिवाइस पर चल रहे हैं, तो आपको करना चाहिए

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

जिसके आधार पर आपके उपयोग-मामले के लिए उपयुक्त है।


1
धन्यवाद। मैं आपसे सहमत हूं कि यह आपके मूल प्रश्न का अधिक विशिष्ट संस्करण है। यदि आपकी मूल खोज में आप आए थे, तो मुझे पूछने की आवश्यकता नहीं होगी।
जेफरी मेयर

5
इन परिभाषाओं से सावधान रहें। जब आप मेनू आइटम 'प्रोजेक्ट> सेट एक्टिव एसडीके> सिम्युलेटर ...' के साथ कोड संकलित करते हैं, तो TARGET_IPHONE_SIMULATOR के रूप में TARGET_OS_IPHONE चर दोनों परिभाषित होते हैं! तो तर्क को अलग करने का एकमात्र सही तरीका नीचे पीट (धन्यवाद दोस्त) द्वारा इंगित किया गया है।
वादिम

5
#If और #ifdef अंतर देखें। मेरे लिए यह गलत व्यवहार का कारण था।
एंटोन

7
शायद टार्गेटकंडिशनल्स को शामिल करने की आवश्यकता को कम कर दिया गया है क्योंकि यह लिखा गया था, लेकिन बस यह नोट करना चाहता था कि #if TARGET_IPHONE_SIMULATOR अभी बिना टार्गेट-कॉर्डिनेशन के काम करता है।
dmur

1
@Dimitris यह अच्छा अभ्यास है। आप नहीं जानते कि TARGET_OS_SIMULATOR को कैसे परिभाषित किया गया है, इसलिए (TARGET_OS_SIMULATOR) TARGET_OS_SIMULATOR के समान नहीं हो सकता है
Airsource Ltd '19

106

अपडेटेड कोड:

यह आधिकारिक तौर पर काम करने के लिए है।

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

मूल पद (पदावनत)

यदि आप एक सिम्युलेटर में चल रहे हैं तो यह कोड आपको बताएगा।

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

7
IOS 8 और Xcode 6.1.1 के रूप में TARGET_OS_IPHONE सिम्युलेटर पर सच है।
मल्हल

3
यह नए XCode संस्करणों पर कोई चिंता नहीं करता है
Fabio Napodano

1
जब तक आप 2016 में हैं और 64 बिट सिम्युलेटर चलाते हैं। या 2019 में इंटेल प्रोसेसर वाले आईफोन पर अपना कोड चलाएं।
gnasher729

61

पूर्व-प्रोसेसर निर्देश नहीं, लेकिन यह वही था जो मैं इस प्रश्न के लिए आया था;

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

9
[model compare:iPhoneSimulator] == NSOrderedSameके रूप में लिखा जाना चाहिए[model isEqualToString:iPhoneSimulator]
user102008

18
या [model hasSuffix:@"Simulator"]यदि आप सामान्य रूप से केवल "सिम्युलेटर" के बारे में परवाह करते हैं, तो विशेष रूप से iPhone या iPad नहीं । यह जवाब iPad सिम्युलेटर के लिए काम नहीं करेगा :)
Nuthatch

अपवोटेड क्योंकि न्यूटच की टिप्पणी इसे टोटको में सबसे अच्छा उत्तर बनाती है।
ले मोट ज्यूस 19

12
IOS9 में, इसके nameबजाय डिवाइस की जाँच करेंmodel
n.Drake

1
यदि उपयोगकर्ता Simulatorअपने डिवाइस के नाम में शब्द जोड़ता है तो कोड काम नहीं करेगा
mbelsky

55

इसका सबसे अच्छा तरीका है:

#if TARGET_IPHONE_SIMULATOR

और नहीं

#ifdef TARGET_IPHONE_SIMULATOR

चूँकि इसकी हमेशा परिभाषित होती है: 0 या 1


39

अब एक बेहतर तरीका है!

Xcode 9.3 बीटा 4 के रूप में आप #if targetEnvironment(simulator)जांच के लिए उपयोग कर सकते हैं ।

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

UPDATE
Xcode 10 और iOS 12 SDK भी इसका समर्थन करता है।


1
यह एकमात्र ऐसा काम है जो मेरे लिए काम करता है, बाकी समाधान काम नहीं करते।
व्रुतिन राठौड़

नोट यह केवल स्विफ्ट में है।
मैट एस

35

स्विफ्ट के मामले में हम निम्नलिखित को लागू कर सकते हैं

हम संरचना बना सकते हैं जो आपको एक संरचित डेटा बनाने की अनुमति देता है

struct Platform {
    static var isSimulator: Bool {
        #if targetEnvironment(simulator)
            // We're on the simulator
            return true
        #else
            // We're on a device
             return false
        #endif
    }
}

तब यदि हम यह पता लगाना चाहते थे कि स्विफ्ट में डिवाइस या सिम्युलेटर के लिए ऐप बनाया जा रहा है या नहीं।

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

मेरी राय में सबसे साफ कार्यान्वयन, और यह x86_64 और i386 आर्किटेक्चर के लिए जिम्मेदार है। कोर डेटा में एक अजीब डिवाइस बनाम सिम्युलेटर बग को दूर करने में मेरी मदद की। आप ही है वह आदमी!
आयरन जॉन बोनी

5
खेल के मैदान में, आपको एक चेतावनी मिलेगी, "कोड के बाद 'वापसी' कभी भी निष्पादित नहीं होगी"। इसलिए मुझे लगता है कि #if #else #endifबेहतर होगा।
डॉनसॉन्ग


9

वे सभी उत्तर अच्छे हैं, लेकिन यह किसी तरह मेरे जैसे नौसिखिया को भ्रमित करता है क्योंकि यह संकलन जांच और रनटाइम जांच को स्पष्ट नहीं करता है। प्रीप्रोसेसर संकलित समय से पहले हैं, लेकिन हमें इसे स्पष्ट करना चाहिए

यह ब्लॉग लेख दिखाता है कि iPhone सिम्युलेटर का पता कैसे लगाया जाए? स्पष्ट रूप से

क्रम

सबसे पहले, आइए शीघ्र ही चर्चा करते हैं। UIDevice आपको डिवाइस के बारे में पहले से ही जानकारी प्रदान करता है

[[UIDevice currentDevice] model]

जहाँ ऐप चल रहा है उसी के अनुसार आपको "आईफ़ोन सिम्युलेटर" या "आईफ़ोन" लौटाएगा।

संकलन समय

हालाँकि आप जो चाहते हैं वह संकलन समय का उपयोग करना है। क्यों? क्योंकि आप अपने ऐप को सख्ती से सिम्युलेटर के अंदर या डिवाइस पर चलाने के लिए संकलित करते हैं। Apple एक परिभाषित करता है TARGET_IPHONE_SIMULATOR। तो आइए कोड देखें:

#if TARGET_IPHONE_SIMULATOR

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

#endif

1
यह अन्य उत्तरों पर कैसे सुधार करता है?
user151019


5
वर्तमान में, Xcode 7 में, iOS 9 सिम्युलेटर के बजाय भी [[UIDevice currentDevice] model]लौट रहा iPhoneहै iPhone Simulator। इसलिए, मुझे लगता है कि यह सबसे अच्छा तरीका नहीं है।
eMdOS

6

पिछले उत्तर थोड़े दिनांकित हैं। मैंने पाया कि आपको केवल TARGET_IPHONE_SIMULATORमैक्रो को क्वेरी करना है ( किसी अन्य हेडर फ़ाइलों को शामिल करने की आवश्यकता नहीं है [यह मानते हुए कि आप iOS के लिए कोडिंग कर रहे हैं])।

मैंने प्रयास किया TARGET_OS_IPHONEलेकिन वास्तविक डिवाइस और सिम्युलेटर पर चलने पर यह उसी मान (1) को लौटा देता है, इसलिए मैं TARGET_IPHONE_SIMULATORइसके बजाय उपयोग करने की सलाह देता हूं ।


TARGET_OS_IPHONE उस कोड के लिए है जो iOS पर या MacOS X पर चल सकता है। जाहिर है आप चाहते हैं कि कोड सिम्युलेटर पर "iPhone" का व्यवहार करे।
gnasher729

6

मैक ऐप्स के बीच अंतर करने के लिए: #if (आर्च (i386) || आर्च (x86_64)) & + os (OSX) // हम मैक पर चलने वाले एक सिम्युलेटर पर हैं, और मैक ऐप नहीं। (मैक प्लेटफ़ॉर्म में शामिल क्रॉस प्लेटफ़ॉर्म कोड के लिए)
बॉबजेट

4

मैं एक ही समस्या थी, दोनों TARGET_IPHONE_SIMULATORऔर TARGET_OS_IPHONEहमेशा परिभाषित कर रहे हैं, और करने के लिए 1. पीट समाधान काम करता है, निश्चित रूप से स्थापित कर रहे हैं, लेकिन आप कभी भी इंटेल के अलावा कुछ पर निर्माण के लिए हो (संभावना नहीं है, लेकिन कौन जानता है), यहाँ के कुछ है कि के रूप में सुरक्षित है, तो जब तक iPhone हार्डवेयर नहीं बदलेगा (इसलिए आपका कोड हमेशा वहां मौजूद आईफ़ोन के लिए काम करेगा):

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

रखो कि कहीं सुविधाजनक, और फिर बहाना है कि TARGET_*स्थिरांक को सही ढंग से परिभाषित किया गया था।


4

क्या किसी ने यहां दिए गए उत्तर पर विचार किया है ?

मुझे लगता है कि उद्देश्य- c समतुल्य होगा

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

4

स्विफ्ट के लिए 4.2 / xCode 10

मैंने UIDevice पर एक एक्सटेंशन बनाया है, इसलिए मैं आसानी से पूछ सकता हूं कि क्या सिम्युलेटर चल रहा है।

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

उदाहरण के लिए मेरे ऐपडेलगेट में मैं इस पद्धति का उपयोग करता हूं यह तय करने के लिए कि दूरस्थ अधिसूचना के लिए रजिस्टर करना आवश्यक है, जो कि सिम्युलेटर के लिए संभव नहीं है।

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

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

1

सभी प्रकार के "सिमुलेटर" को शामिल करने के लिए

NSString *model = [[UIDevice currentDevice] model];
if([model rangeOfString:@"Simulator" options:NSCaseInsensitiveSearch].location !=NSNotFound)
{
    // we are running in a simulator
}

4
इसका Xcode 7. से कोई लेना-देना नहीं है। यदि आप iOS सिम्युलेटर को iOS8 (Xcode 7 से) चलाते हैं तो यह काम करेगा। यह iOS9 के लिए काम नहीं करेगा, जहां [[UIDevice currentDevice] मॉडल] केवल "iPhone" लौटाता है यदि ऐप iOS सिम्युलेटर से लॉन्च किया गया था
tesla

क्यों नहीं -[NSString containsString]?
गोब

1

स्विफ्ट 4.2 (Xcode 10) के साथ, हम ऐसा कर सकते हैं

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

1
बस एक और कॉपी पेस्ट
जे डो

0

मेरा जवाब @Daniel Magnusson उत्तर और @Nuthatch और @ n.Drake की टिप्पणियों पर आधारित है। और आईओएस 9 और उसके बाद काम करने वाले तेज उपयोगकर्ताओं के लिए कुछ समय बचाने के लिए इसे लिखता हूं।

इसी से मेरा काम बना है:

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

1
यदि उपयोगकर्ता Simulatorअपने डिवाइस के नाम में शब्द जोड़ता है तो कोड काम नहीं करेगा
mbelsky

दुर्भाग्य से XCode 8 के UIDevice.current.nameअनुसार मशीन का नाम सिम्युलेटर चल रहा है (आमतौर पर "साइमन मैकबुक प्रो" जैसा कुछ) अब परीक्षण अविश्वसनीय हो गया है। मैं अभी भी इसे ठीक करने के लिए एक साफ तरीके से देख रहा हूं।
माइकल

0

/// अगर इसका सिम्युलेटर और डिवाइस नहीं तो यह सच है

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

0

ऐप्पल ने निम्नलिखित के साथ सिम्युलेटर के लिए ऐप को लक्षित करने के लिए समर्थन जोड़ा है:

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

0

अगर कुछ भी काम नहीं किया, तो यह कोशिश करो

public struct Platform {

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

}

-4

मेरी राय में, उत्तर (ऊपर और बार-बार प्रस्तुत):

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

इसका सबसे अच्छा जवाब है क्योंकि यह स्पष्ट रूप से RUNTIME पर निष्पादित किया जाता है।


11
मैं असहमत हूं। यह कोड आपके उत्पाद में समाप्त हो जाता है, जबकि एक संकलक निर्देश डिवाइस को अनावश्यक - नियमित बाहर रखता है।
नौ पत्थर

1
कंपाइलर निर्देश काम करते हैं क्योंकि डिवाइस और सिमुलेटर पूरी तरह से अलग-अलग लक्ष्य हैं - यानी आप दोनों पर एक ही बाइनरी का उपयोग नहीं करेंगे। यह है विभिन्न हार्डवेयर के लिए संकलित की, तो यह उस स्थिति में समझ में आता है।
ब्रैड पार्क्स

RUNTIME पर निष्पादित होने के कारण यह सबसे खराब उत्तर है।
gnasher729

-4

इसने मेरे लिए सबसे अच्छा काम किया

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


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

}

2
Xcode 7.3 पर, iPhone 6 Plus सिम्युलेटर रिटर्न देता है "iPhone"
एरिक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.