Di Objective-C kita bisa tahu apakah aplikasi sedang dibangun untuk perangkat atau simulator menggunakan makro:
#if TARGET_IPHONE_SIMULATOR
// Simulator
#else
// Device
#endif
Ini adalah kompilasi makro waktu dan tidak tersedia saat runtime.
Bagaimana saya bisa mencapai hal yang sama di Swift?
Jawaban:
Perbarui 30/01/19
Meskipun jawaban ini dapat berfungsi, solusi yang disarankan untuk pemeriksaan statis (seperti yang diklarifikasi oleh beberapa insinyur Apple) adalah dengan menentukan flag kompiler khusus yang menargetkan iOS Simulators. Untuk instruksi terperinci tentang bagaimana melakukannya, lihat jawaban @ mbelsky .
Jawaban asli
Jika Anda memerlukan pemeriksaan statis (mis. Bukan runtime jika / selain itu) Anda tidak dapat mendeteksi simulator secara langsung, tetapi Anda dapat mendeteksi iOS pada arsitektur desktop seperti berikut
Setelah versi Swift 4.1
Untuk klarifikasi lebih lanjut, Anda dapat memeriksa proposal Swift SE-0190
Jelas, ini salah pada perangkat, tetapi mengembalikan true untuk iOS Simulator, seperti yang ditentukan dalam dokumentasi :
Jika Anda mengembangkan untuk simulator selain iOS, Anda dapat dengan mudah memvariasikan
os
parameter: misDeteksi simulator watchOS
Deteksi simulator tvOS
Atau, bahkan, mendeteksi simulator apa pun
Jika Anda tidak keberatan dengan pemeriksaan runtime, Anda dapat memeriksa
TARGET_OS_SIMULATOR
variabel (atauTARGET_IPHONE_SIMULATOR
di iOS 8 dan di bawah), yang benar pada simulator.Harap perhatikan bahwa ini berbeda dan sedikit lebih terbatas daripada menggunakan bendera preprosesor. Misalnya Anda tidak akan dapat menggunakannya di tempat di mana
if/else
sintaksis tidak valid (misalnya di luar cakupan fungsi).Katakan, misalnya, bahwa Anda ingin memiliki impor yang berbeda pada perangkat dan pada simulator. Ini tidak mungkin dengan pemeriksaan dinamis, sedangkan itu sepele dengan pemeriksaan statis.
Juga, karena flag diganti dengan a
0
atau a1
oleh preprocessor cepat, jika Anda langsung menggunakannya dalamif/else
ekspresi kompiler akan memunculkan peringatan tentang kode yang tidak terjangkau.Untuk mengatasi peringatan ini, lihat salah satu jawaban lainnya.
sumber
arch(i386) && os(iOS)
.#if targetEnvironment(simulator)
:) ( github.com/apple/swift-evolution/blob/master/proposals/… )LUAR BIASA UNTUK SWIFT 4.1. Gunakan
#if targetEnvironment(simulator)
sebagai gantinya. SumberUntuk mendeteksi simulator di Swift, Anda dapat menggunakan konfigurasi bangunan:
Sekarang Anda dapat menggunakan pernyataan ini untuk mendeteksi simulator:
Anda juga dapat memperluas kelas UIDevice:
sumber
xcconfig
file dengan menggunakanOTHER_SWIFT_FLAGS = TARGET_OS_EMBEDDED
danOTHER_SWIFT_FLAGS[sdk=embeddedsimulator*] = TARGET_OS_SIMULATOR
menimpa untuk Simulator.Info Diperbarui per 20 Februari 2018
Sepertinya @russbishop memiliki jawaban otoritatif yang menjadikan jawaban ini "salah" - meskipun tampaknya bekerja lama sekali.
Mendeteksi jika aplikasi sedang dibangun untuk perangkat atau simulator di Swift
Jawaban Sebelumnya
Berdasarkan jawaban @ WZW dan komentar @ Pang, saya membuat sebuah utilitas utilitas sederhana. Solusi ini menghindari peringatan yang dihasilkan oleh jawaban @ WZW.
Contoh penggunaan:
sumber
public let IS_SIMULATOR = (TARGET_OS_SIMULATOR != 0)
... hal yang sama, disederhanakan. Terima kasih +1TARGET_OS_SIMULATOR != 0
adalah sudah dalam jawabannya . Ini solusi yang diberikan oleh Daniel. Tidak perlu menambahkannya lagi dalam variabel gratis, itu sudah ada di sana. Jika Anda berpikir memilikinya dalam suatu struct adalah buruk dan memilikinya dalam variabel bebas lebih baik maka posting komentar tentang ini atau buat jawaban Anda sendiri. Terima kasih.Dari Xcode 9.3
iOS 9+:
Swift 3:
Sebelum iOS 9:
Tujuan-C:
sumber
will never be executed
peringatanCepat 4
Anda sekarang dapat menggunakan
targetEnvironment(simulator)
sebagai argumen.Diperbarui untuk Xcode 9.3
sumber
Izinkan saya mengklarifikasi beberapa hal di sini:
TARGET_OS_SIMULATOR
tidak diatur dalam kode Swift dalam banyak kasus; Anda mungkin secara tidak sengaja mengimpornya karena header penghubung tetapi ini rapuh dan tidak didukung. Bahkan juga tidak mungkin dalam kerangka kerja. Inilah sebabnya mengapa beberapa orang bingung tentang apakah ini berfungsi di Swift.Untuk melakukan pemeriksaan dinamis:
Memeriksa
ProcessInfo.processInfo.environment["SIMULATOR_DEVICE_NAME"] != nil
baik-baik saja.Anda juga bisa mendapatkan model dasar yang disimulasikan dengan memeriksa
SIMULATOR_MODEL_IDENTIFIER
yang akan mengembalikan string sepertiiPhone10,3
.Untuk melakukan pemeriksaan statis:
Xcode 9.2 & sebelumnya: tentukan flag kompilasi Swift Anda sendiri (seperti yang ditunjukkan pada jawaban lain).
Xcode 9.3+ menggunakan kondisi targetEnvironment baru:
sumber
targetEnvironment
mendarat di Xcode 9.3. Anda memerlukan versi Xcode yang lebih baru.Apa yang bekerja untuk saya sejak Swift 1.0 sedang memeriksa arsitektur selain lengan:
sumber
Runtime, tetapi lebih sederhana daripada sebagian besar solusi lain di sini:
Atau, Anda bisa memanggil fungsi pembantu Objective-C yang mengembalikan boolean yang menggunakan makro preprocessor (terutama jika Anda sudah melakukan mixing dalam proyek Anda).
Sunting: Bukan solusi terbaik, terutama pada Xcode 9.3. Lihat jawaban HotJard
sumber
== 0
bukan!= 0
. Menggunakannya seperti yang tertulis di atas, bahkan denganelse
blok setelahnya, tidak menghasilkan peringatan apa pun di Swift 4 Xcode Versi 9.2 (9C40b)Dalam sistem modern:
Itu mudah.
sumber
TARGET_IPHONE_SIMULATOR
sudah ditinggalkan di iOS 9.TARGET_OS_SIMULATOR
adalah penggantinya. JugaTARGET_OS_EMBEDDED
tersedia.Dari TargetConditionals.h :
sumber
Saya harap ekstensi ini berguna.
Pemakaian:
sumber
Dalam Xcode 7.2 (dan sebelumnya tetapi saya belum menguji seberapa awal), Anda dapat mengatur flag build khusus platform "-D TARGET_IPHONE_SIMULATOR" untuk "Any iOS Simulator".
Lihat di pengaturan pembangunan proyek di bawah "Kompresor Swift - Bendera Pelanggan" dan kemudian atur bendera di "Bendera Swift Lain". Anda dapat mengatur flag khusus platform dengan mengklik ikon 'plus' saat Anda mengarahkan kursor ke konfigurasi build.
Ada beberapa keuntungan melakukannya dengan cara ini: 1) Anda dapat menggunakan tes kondisional yang sama ("#jika TARGET_IPHONE_SIMULATOR") dalam kode Swift dan Objective-C Anda. 2) Anda bisa mengkompilasi variabel yang hanya berlaku untuk setiap build.
Tangkapan layar pengaturan pengaturan Xcode
sumber
Semua dijelaskan di sini Darwin.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
sumber
Saya menggunakan kode di bawah ini di Swift 3
sumber
Swift 4:
Saat ini, saya lebih suka menggunakan kelas ProcessInfo untuk mengetahui apakah perangkat tersebut merupakan simulator dan jenis perangkat apa yang digunakan:
Tetapi, seperti yang Anda ketahui,
simModelCode
bukan kode yang nyaman untuk memahami dengan segera simulator jenis apa yang diluncurkan, jadi, jika perlu, Anda dapat mencoba melihat jawaban SO lainnya untuk menentukan model iPhone / perangkat saat ini dan untuk memiliki lebih manusiawi string yang bisa dibaca.sumber
Berikut adalah contoh Xcode 11 Swift yang didasarkan pada jawaban HotJard yang luar biasa di atas , ini juga menambahkan
isDevice
Bool dan menggunakanSIMULATOR_UDID
bukan nama. Tugas variabel dilakukan pada setiap baris sehingga Anda bisa lebih mudah memeriksanya di debugger jika Anda mau.Ada juga entri kamus
DTPlatformName
yang harus berisisimulator
.sumber
Gunakan kode di bawah ini:
Bekerja untuk
Swift 4
danXcode 9.4.1
sumber
Xcode 11, Swift 5
sumber
Selain jawaban lainnya.
Di Objective-c, Pastikan Anda menyertakan TargetConditionals .
#include <TargetConditionals.h>
sebelum digunakan
TARGET_OS_SIMULATOR
.sumber