Uygulamamın iphone simülatöründe çalışıp çalışmadığını programlı olarak nasıl belirleyebilirim?


270

Soruda belirtildiği gibi, kodumun simülatörde çalışıp çalışmadığını bilmek isterim, ancak aynı zamanda çalışan veya simüle edilen belirli iphone sürümünü bilmekle de ilgilenirim.

EDIT: Soru adına 'programlı' kelimesini ekledim. Sorumun amacı, hangi sürümün / simülatörün çalıştığına bağlı olarak kodu dinamik olarak dahil edebilmek / hariç tutabilmek.


Bir işlemci öncesi direktifin dinamik olduğundan emin değilim (yine de aradığınız şey olabilir). Yönerge, onu inşa ettiğinizde, nereye koşacağını bildiğiniz anlamına gelir.
WiseOldDuck

Yanıtlar:


356

Zaten sordum, ama çok farklı bir başlık ile.

İPhone için derlerken #defines Xcode tarafından ayarlanır

Cevabımı oradan tekrarlayacağım:

"Kaynak kodu koşullu olarak derleme" altında SDK dokümanlarında bulunur

İlgili tanım, iOS çerçevesi içinde /usr/include/TargetConditionals.h dosyasında tanımlanan TARGET_OS_SIMULATOR şeklindedir. Takım zincirinin önceki sürümlerinde şunları yazmak zorundaydınız:

#include "TargetConditionals.h"

ancak bu artık geçerli (Xcode 6 / iOS8) araç zincirinde gerekli değildir.

Örneğin, cihazda çalışıp çalışmadığınızı kontrol etmek istiyorsanız,

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

hangisinin kullanım durumunuza uygun olduğuna bağlı olarak.


1
Teşekkürler. Size katılıyorum, bu orijinal sorunuzun daha spesifik bir versiyonu. Sizinki orijinal aramamda ortaya çıksaydı, sormam bile gerekmiyordu.
Jeffrey Meyer

5
Bu tanımlara dikkat edin. Kodu 'Proje> Aktif SDK Ayarla> Simülatör…' menü öğesiyle derlediğinizde TARGET_IPHONE_SIMULATOR olarak TARGET_OS_IPHONE değişkenleri tanımlanır! Bu yüzden mantığı ayırmanın tek doğru yolu Pete tarafından belirtilmiştir (Teşekkürler ahbap).
Vadim

5
#İf ve #ifdef farkını izleyin. Benim için yanlış davranışın nedeni buydu.
Anton

7
Belki de bu yazıldığından beri TargetConditionals'ı ekleme ihtiyacı ortadan kaldırılmıştır, ancak #if TARGET_IPHONE_SIMULATOR'un TargetConditionals.h'yi içermeden çalıştığını belirtmek istedik.
dmur

1
@Dimitris İyi bir uygulama. TARGET_OS_SIMULATOR'un nasıl tanımlandığını bilmiyorsunuz, bu yüzden! (TARGET_OS_SIMULATOR)! TARGET_OS_SIMULATOR
Airsource Ltd

106

Güncellenmiş kod:

Bunun resmi olarak çalıştığı iddia ediliyor.

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

Orijinal yayın (kullanımdan kaldırıldığından beri)

Bu kod, bir simülatörde çalışıp çalışmadığınızı söyleyecektir.

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

7
İOS 8 ve Xcode 6.1.1'den itibaren TARGET_OS_IPHONE simülatörde doğrudur.
malhal

3
Bu artık yeni XCode sürümlerinde çalışmaz
Fabio Napodano

1
2016'da değilseniz ve 64 bit simülatör çalıştırmazsanız. Veya 2019'da kodunuzu Intel işlemcili bir iPhone'da çalıştırın.
gnasher729

61

İşlemci öncesi yönerge değil, ama bu soruya geldiğimde aradığım şey buydu;

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

9
[model compare:iPhoneSimulator] == NSOrderedSameşu şekilde yazılmalıdır[model isEqualToString:iPhoneSimulator]
user102008

18
Veya [model hasSuffix:@"Simulator"]yalnızca genel olarak "simülatör" ile ilgileniyorsanız , özellikle iPhone veya iPad ile ilgilenmezseniz . Bu cevap iPad simülatörü için işe yaramaz :)
Nuthatch

Nuthatch'ın yorumu bunu toto'daki en iyi cevap haline getirdiğinden dolayı seçildi.
Le Mot Juiced

12
İOS9'da,namemodel
n.Drake

1
Bir kullanıcı Simulatorcihaz adına kelime eklerse kod çalışmaz
mbelsky

55

Bunu yapmanın en iyi yolu:

#if TARGET_IPHONE_SIMULATOR

ve yok

#ifdef TARGET_IPHONE_SIMULATOR

her zaman tanımlandığı için: 0 veya 1


39

ŞİMDİ DAHA İYİ BİR YOL VAR!

Xcode 9.3 beta 4'ten itibaren #if targetEnvironment(simulator)kontrol etmek için kullanabilirsiniz .

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

UPDATE
Xcode 10 ve iOS 12 SDK da bunu destekliyor.


1
Benim için işe yarayan tek şey bu, geri kalan çözümler işe yaramadı.
Vrutin Rathod

Not Bu sadece hızlıdır.
Matt S.

35

Swift durumunda aşağıdakileri uygulayabiliriz

Yapısal bir veri oluşturmanıza izin veren yapı oluşturabiliriz

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

Daha sonra Swift'te uygulama cihaz veya simülatör için uygulama oluşturulup oluşturulmadığını tespit etmek istersek.

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

Bence en temiz uygulama ve bu x86_64 ve i386 mimarilerini açıklıyor. Çekirdek Veriler'deki garip bir aygıta karşı simülatör hatası üstesinden gelmeme yardımcı oldu. Sen adamsın!
Iron John Bonney

5
Playground'da "dönüşten sonraki kod asla yürütülmeyecek" uyarısı alırsınız. Bu yüzden #if #else #endifdaha iyi olacağını düşünüyorum .
DawnSong

12

İçin İşleri Swift 5veXcode 11.3.1

Bu kodu kullanın:

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

9

Tüm bu cevaplar iyi, ama derleme kontrolü ve çalışma zamanı kontrolünü netleştirmediği için bir şekilde benim gibi acemi karıştırıyor. Önişlemci derleme süresinden önce, ama daha açık hale getirmeliyiz

Bu blog makalesinde iPhone simülatörü nasıl algılanır? Açıkça

Çalışma süresi

Her şeyden önce, kısaca tartışalım. UIDevice, cihaz hakkında zaten bilgi sağlar

[[UIDevice currentDevice] model]

uygulamanın çalıştığı yere göre size “iPhone Simulator” veya “iPhone” döndürecektir.

Derleme zamanı

Ancak istediğiniz zaman derleme zaman tanımları kullanmaktır. Neden? Çünkü uygulamanızı kesinlikle Simülatör içinde veya cihazda çalışacak şekilde derliyorsunuz. Apple adlı bir tanım yapar TARGET_IPHONE_SIMULATOR. O halde koda bakalım:

#if TARGET_IPHONE_SIMULATOR

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

#endif

1
Bu diğer cevaplarda nasıl gelişir?
user151019

@Mark Biraz
açıklar

5
Şu anda Xcode 7'de iOS 9 Simulator yerine de [[UIDevice currentDevice] model]geri dönüyor . Bence bu en iyi yaklaşım değil. iPhoneiPhone Simulator
eMdOS

6

Önceki cevaplar biraz tarihli. Tüm yapmanız gereken TARGET_IPHONE_SIMULATORmakro sorgu ( başka bir başlık dosyaları dahil etmeye gerek yok) olduğunu buldum [iOS için kodlama yaptığınızı varsayarak).

Denedim TARGET_OS_IPHONEama gerçek bir cihaz ve simülatörde çalışırken aynı değeri (1) döndürdü, bu yüzden TARGET_IPHONE_SIMULATORbunun yerine kullanılmasını öneriyorum .


TARGET_OS_IPHONE, iOS veya MacOS X üzerinde çalışabilecek kodlar içindir. Açıkçası bu kodun bir simülatörde "iPhone" yolunda davranmasını istersiniz.
gnasher729


4

Aynı problemi yaşadım TARGET_IPHONE_SIMULATORve TARGET_OS_IPHONEher zaman tanımlandım ve 1'e ayarlandım. Elbette Pete'nin çözümü işe yarıyor, ancak intel'den başka bir şey üzerine inşa ederseniz (olası değil, ama kim bilir), iphone donanımı değişmediği sürece (kodunuz her zaman şu anda orada olan iphone'lar için çalışacaktır):

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

Bunu uygun bir yere koyun ve TARGET_*sabitlerin doğru tanımlandığını iddia edin .


4

Burada verilen cevabı düşünen var mı?

Herhalde obj-c eşdeğeri

+ (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

Swift 4.2 / xCode 10 için

UIDevice üzerinde bir uzantı oluşturdum, böylece simülatörün çalışıp çalışmadığını kolayca sorabilirim.

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

Benim içinde AppDelegate örneğin ben uzaktan bildirimi için kayıt Hava karar vermek için bu yöntemi kullanmak simülatörü mümkün olmadığı, gereklidir.

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

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

1

Her tür "simülatör" dahil etmek

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

4
Xcode 7 ile ilgisi yok. İOS Simulator'u iOS8 ile (Xcode 7'den) çalıştırırsanız, bu işe yarayacaktır. İOS Simulator'dan uygulama başlatılırsa [[UIDevice currentDevice] modelinin] yalnızca "iPhone" döndürdüğü iOS9 için çalışmaz
Stefan

neden olmasın -[NSString containsString]?
Gobe

1

Swift 4.2 (Xcode 10) ile bunu yapabiliriz

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

1
Başka bir kopya yapıştır
J. Doe

0

Cevabım @Daniel Magnusson cevap ve @Nuthatch ve @ n.Drake yorumlarına dayanmaktadır. ve iOS9 ve sonrasında çalışan hızlı kullanıcılar için biraz zaman kazanmak için yazıyorum.

Benim için işe yarayan buydu:

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

1
Bir kullanıcı Simulatorcihaz adına kelime eklerse kod çalışmaz
mbelsky

Ne yazık ki XCode 8 ile UIDevice.current.nameSimülatörün üzerinde çalıştığı makinenin adını bildiriyor (genellikle "Simon'un MacBook Pro" gibi bir şey), bu yüzden test güvenilmez hale geldi. Hala düzeltmek için temiz bir yol arıyorum.
Michael

0

/// Bir cihaz değil, simülatörü ise doğru döndürür

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

0

Apple, aşağıdaki simülatör için uygulamanın hedeflendiğini kontrol etmek için destek ekledi:

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

0

hiçbir şey işe yaramadıysa, bunu deneyin

public struct Platform {

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

}

-4

Bence cevap (yukarıda sunuldu ve aşağıda tekrarlandı):

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

en iyi cevaptır çünkü ÇALIŞMA DERECESİ yerine RUNTIME yürütülür.


11
Katılmıyorum. Bu kod ürününüzde sona erer, ancak bir derleyici yönergesi - cihazdaki gereksiz - rutini dışarıda tutar.
Dokuz taş

1
Derleyici yönergeleri çalışır çünkü cihaz ve simülatörler tamamen farklı derleme hedefleridir - yani her ikisinde de aynı ikili dosyayı kullanmazsınız. Bu sahiptir farklı donanıma derlenmiş olması, bu nedenle bu durumda mantıklı.
Brad Parks

ÇALIŞMA ZAMANI'nda yürütülmesi, onu en kötü yanıt haline getirir .
gnasher729

-4

Bu benim için en iyisi

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


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

}

2
Xcode 7.3'te iPhone 6 Plus Simulator geri döner "iPhone".
Eric
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.