كيف يمكنني تحديد ما إذا كان تطبيقي يعمل برمجيًا في جهاز محاكاة iPhone؟

StackOverflow https://stackoverflow.com/questions/458304

سؤال

كما يشير السؤال، أود بشكل أساسي معرفة ما إذا كان الكود الخاص بي يعمل في جهاز المحاكاة أم لا، ولكني مهتم أيضًا بمعرفة إصدار iPhone المحدد الذي يتم تشغيله أو تتم محاكاته.

يحرر:أضفت كلمة "برمجيًا" إلى اسم السؤال.الهدف من سؤالي هو أن أكون قادرًا على تضمين/استبعاد التعليمات البرمجية ديناميكيًا اعتمادًا على الإصدار/المحاكي الذي يتم تشغيله، لذلك سأبحث حقًا عن شيء مثل توجيه ما قبل المعالج الذي يمكن أن يزودني بهذه المعلومات.

هل كانت مفيدة؟

المحلول

وسأل إذا، ولكن مع عنوان مختلف للغاية.

ما #defines تم إعدادها من قبل كسكودي عندما تجميع آيفون

وسوف أكرر جوابي من هناك:

وانها في مستندات SDK تحت عنوان "تجميع شفرة المصدر مشروط"

والتعريف ذات الصلة هو TARGET_OS_SIMULATOR، التي تم تعريفها في /usr/include/TargetConditionals.h في إطار دائرة الرقابة الداخلية. في الإصدارات السابقة من toolchain، كان عليك أن تكتب:

#include "TargetConditionals.h"

ولكن هذا لم يعد من الضروري على (إكس كود 6 / iOS8) toolchain الحالي.

وهكذا، على سبيل المثال، إذا كنت تريد أن تتأكد من يعمل على الجهاز، يجب عليك القيام به

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

واعتمادا على يناسب استخدامك حدة.

نصائح أخرى

تحليل كود تحديث:

وهذا هو المفترض للعمل رسميا.

#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

وليس قبل معالج التوجيه، ولكن هذا ما كنت أبحث عنه عندما جئت إلى هذه المسألة؛

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

وأفضل طريقة للقيام بذلك هي:

#if TARGET_IPHONE_SIMULATOR

وليس

#ifdef TARGET_IPHONE_SIMULATOR

ومنذ المحددة لها دائما: 0 أو 1

هناك طريقة أفضل الآن!

اعتبارًا من الإصدار التجريبي الرابع من Xcode 9.3، يمكنك استخدامه #if targetEnvironment(simulator) للتأكد.

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

تحديث
يدعم Xcode 10 وiOS 12 SDK هذا أيضًا.

في حالة Swift يمكننا تنفيذ ما يلي

يمكننا إنشاء هيكل يسمح لك بإنشاء بيانات منظمة

struct Platform {
    static let isSimulator: Bool = {
        #if arch(i386) || arch(x86_64)
            return true
        #endif
        return false
    }()
}

ثم إذا أردنا اكتشاف ما إذا كان التطبيق مصممًا لجهاز أو جهاز محاكاة في Swift، فعندئذٍ.

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

كل هذه الإجابات جيدة، لكنها تربك بطريقة أو بأخرى المبتدئين مثلي لأنها لا توضح التحقق من الترجمة والتحقق من وقت التشغيل.المعالج المسبق موجود قبل وقت الترجمة، ولكن يجب أن نجعل الأمر أكثر وضوحًا

تظهر هذه المقالة بلوق كيفية الكشف عن محاكي iPhone؟ بوضوح

مدة العرض

أولا وقبل كل شيء، دعونا نناقش قريبا.يوفر لك UIDevice بالفعل معلومات حول الجهاز

[[UIDevice currentDevice] model]

سيعيد لك "iPhone Simulator" أو "iPhone" وفقًا لمكان تشغيل التطبيق.

وقت الترجمة

لكن ما تريده هو استخدام وقت الترجمة المحدد.لماذا؟لأنك تقوم بتجميع تطبيقك بشكل صارم ليتم تشغيله إما داخل جهاز المحاكاة أو على الجهاز.تقدم شركة Apple تعريفًا يسمى TARGET_IPHONE_SIMULATOR.لذلك دعونا نلقي نظرة على الكود:

#if TARGET_IPHONE_SIMULATOR

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

#endif

ويعمل لSwift 4 وXcode 9.4.1

استخدم هذا الرمز:

#if targetEnvironment(simulator)
   // Simulator
#else
   // Device
#endif

الإجابات السابقة مؤرخة قليلاً.لقد وجدت أن كل ما عليك فعله هو الاستعلام عن TARGET_IPHONE_SIMULATOR دقيق (لا حاجة لتضمين أي ملفات رأس أخرى [بافتراض أنك تقوم بالبرمجة لنظام iOS]).

حاولت TARGET_OS_IPHONE ولكنها أعادت نفس القيمة (1) عند التشغيل على جهاز ومحاكي فعليين، ولهذا السبب أوصي باستخدامه TARGET_IPHONE_SIMULATOR بدلاً من.

وكان لي نفس المشكلة، يتم تعريف كل من TARGET_IPHONE_SIMULATOR وTARGET_OS_IPHONE دائما، ويتم تعيين إلى 1. يعمل حل بيت، بطبيعة الحال، ولكن إذا كنت يحدث من أي وقت مضى أن نبني على شيء آخر غير إنتل (غير محتمل، ولكن من يدري)، وهنا شيء أن يكون في مأمن طالما لا يتغير الأجهزة فون (حتى التعليمات البرمجية ستعمل دائما من أجل فون حاليا هناك):

#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.2 / xCode 10

لقد قمت بإنشاء ملحق على UDevice، لذا يمكنني بسهولة السؤال عما إذا كان جهاز المحاكاة قيد التشغيل.

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

في AppDelegate على سبيل المثال، أستخدم هذه الطريقة لتحديد ما إذا كان التسجيل للإشعارات عن بعد ضروريًا، وهو أمر غير ممكن لجهاز المحاكاة.

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

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

هل قام أي شخص يعتبر الجواب قدمت <لأ href = "https://github.com/EddyVerbruggen/nativescript-secure-storage/blob/70aa5e88691c073312e334c9963c444c3f4d86d5/secure-storage.ios.ts#L12-L24" يختلط = "نوفولو noreferrer "> هنا ؟

وأعتقد أن ما يعادل الهدف-ج أن يكون

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

لتشمل جميع أنواع "محاكاة"

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

ومع سويفت 4.2 (كسكودي 10)، يمكننا أن نفعل هذا

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

ويستند جوابي علىDaniel ماجنوسون الجواب وتعليقاتNuthatch و @n.Drake. وأنا أكتب لإنقاذ بعض الوقت للمستخدمين بسرعة العمل على iOS9 وما بعده.

وهذا ما عملت بالنسبة لي:

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

و/// عرض true إذا كانت محاكاة وليس جهاز

public static var isSimulator: Bool {
    #if (arch(i386) || arch(x86_64)) && os(iOS)
        return true
    #else
        return false
    #endif
}
ويستهدف دعم

وأبل قد أضاف للتحقق من التطبيق لجهاز محاكاة بما يلي:

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

إذا لم ينجح شيء، جرب هذا

public struct Platform {

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

}

وهذا عمل بالنسبة لي أفضل

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


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

}

في رأيي، فإن الجواب (عرض أعلاه وتتكرر أدناه):

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

وهو أفضل إجابة لأنه يتم تنفيذ الواضح في RUNTIME مقابل كونه DIRECTIVE ترجمة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top