Dalam C / C ++ / Objective C Anda dapat mendefinisikan makro menggunakan preprosesor kompiler. Selain itu, Anda dapat menyertakan / mengecualikan beberapa bagian kode menggunakan preprosesor kompiler.
#ifdef DEBUG
// Debug-only code
#endif
Apakah ada solusi serupa di Swift?
Jawaban:
Ya kamu bisa melakukannya.
Di Swift Anda masih dapat menggunakan macro preprocessor "# if / # else / # endif" (meskipun lebih terbatas), sesuai dengan dokumen Apple . Ini sebuah contoh:
Sekarang, Anda harus mengatur simbol "DEBUG" di tempat lain. Atur di bagian "Swift Compiler - Custom Flags", baris "Other Swift Flags". Anda menambahkan simbol DEBUG dengan
-D DEBUG
entri.Seperti biasa, Anda dapat mengatur nilai yang berbeda saat di Debug atau saat di Rilis.
Saya mengujinya dalam kode nyata dan berfungsi; tampaknya tidak diakui di taman bermain.
Anda dapat membaca posting asli saya di sini .
CATATAN PENTING:
-DDEBUG=1
tidak berfungsi. Hanya-D DEBUG
bekerja. Tampaknya kompiler mengabaikan bendera dengan nilai tertentu.sumber
-D DEBUG
seperti yang disebutkan di atas, Anda juga perlu mendefinisikanDEBUG=1
diApple LLVM 6.0 - Preprocessing
->Preprocessor Macros
.-DDEBUG
dari jawaban ini: stackoverflow.com/a/24112024/747369 .DEBUG=1
kePreprocessor Macros
, jika Anda tidak ingin menggunakannya dalam kode Objective-C.Sebagaimana dinyatakan dalam Apple Documents
Saya telah berhasil mencapai apa yang saya inginkan dengan menggunakan Konfigurasi Build khusus:
Inilah cara Anda memeriksa target:
Diuji menggunakan Swift 2.2
sumber
-DLOCAL
, pada saya#if LOCAl #else #endif
, itu jatuh ke#else
bagian. Saya menggandakan target asliAppTarget
dan mengganti namanya menjadiAppTargetLocal
& mengatur bendera kustom.#if LOCAL
, hasil yang dimaksudkan ketika saya menjalankan dengan simulator dan jatuh ke dalam#else
selama pengujian. Saya ingin itu jatuh ke dalam#if LOCAL
juga selama pengujian.Dalam banyak situasi, Anda tidak benar-benar membutuhkan kompilasi bersyarat ; Anda hanya perlu perilaku kondisional yang dapat Anda aktifkan dan matikan. Untuk itu, Anda dapat menggunakan variabel lingkungan. Ini memiliki keuntungan besar yang sebenarnya tidak perlu Anda kompilasi ulang.
Anda dapat mengatur variabel lingkungan, dan dengan mudah mengaktifkan atau menonaktifkannya, di editor skema:
Anda dapat mengambil variabel lingkungan dengan NSProcessInfo:
Inilah contoh kehidupan nyata. Aplikasi saya hanya berjalan di perangkat, karena menggunakan perpustakaan musik, yang tidak ada di Simulator. Lalu, bagaimana cara mengambil screenshot di Simulator untuk perangkat yang bukan milik saya? Tanpa cuplikan layar itu, saya tidak bisa mengirim ke AppStore.
Saya membutuhkan data palsu dan cara pemrosesan yang berbeda . Saya memiliki dua variabel lingkungan: satu yang, ketika dinyalakan, memberi tahu aplikasi untuk menghasilkan data palsu dari data nyata saat berjalan di perangkat saya; yang lain, ketika dihidupkan, menggunakan data palsu (bukan perpustakaan musik yang hilang) saat berjalan di Simulator. Mengaktifkan / menonaktifkan mode khusus tersebut mudah berkat kotak centang variabel lingkungan di editor Skema. Dan bonusnya adalah saya tidak dapat menggunakannya secara tidak sengaja di build App Store saya, karena pengarsipan tidak memiliki variabel lingkungan.
sumber
Perubahan besar
ifdef
penggantian muncul dengan Xcode 8. yaitu penggunaan Kondisi Kompilasi Aktif .Lihat Membangun dan Menautkan dalam Catatan rilis Xcode 8 .
Pengaturan build baru
Pengaturan baru:
SWIFT_ACTIVE_COMPILATION_CONDITIONS
Sebelumnya, kami harus mendeklarasikan flag kompilasi bersyarat Anda di bawah OTHER_SWIFT_FLAGS, ingat untuk menambahkan "-D" ke pengaturan. Misalnya, mengkompilasi dengan nilai MYFLAG secara kondisional:
Nilai untuk ditambahkan ke pengaturan
-DMYFLAG
Sekarang kita hanya perlu meneruskan nilai MYFLAG ke pengaturan baru. Saatnya untuk memindahkan semua nilai kompilasi bersyarat itu!
Silakan merujuk ke tautan di bawah ini untuk lebih banyak fitur Pengaturan Swift dalam Xcode 8: http://www.miqu.me/blog/2016/07/31/xcode-8-new-build-settings-and-analyzer-improvements/
sumber
Pada Swift 4.1, jika yang Anda butuhkan hanyalah memeriksa apakah kode tersebut dibangun dengan konfigurasi debug atau rilis, Anda dapat menggunakan fungsi bawaan:
_isDebugAssertConfiguration()
(true ketika optimisasi diatur ke-Onone
)(tidak tersedia di Swift 3+)_isReleaseAssertConfiguration()
(true ketika optimisasi diatur ke-O
)_isFastAssertConfiguration()
(true ketika optimisasi diatur ke-Ounchecked
)misalnya
Dibandingkan dengan macro preprocessor,
-D DEBUG
bendera khusus untuk menggunakannya✗ Tidak terdokumentasi, yang berarti fungsi dapat dihapus dalam pembaruan apa pun (tetapi harus aman dari AppStore karena pengoptimal akan mengubahnya menjadi konstanta)
@testable
atribut , nasib tidak pasti pada Swift masa depan.✗ Menggunakan di jika / lain akan selalu menghasilkan peringatan "Tidak akan pernah dieksekusi".
sumber
if _isDebugAssertConfiguration()
akan dievaluasiif false
dalam mode rilis danif true
mode debug.Xcode 8 ke atas
Gunakan pengaturan Kondisi Kompilasi Aktif dalam pengaturan Build / kompiler Swift - Bendera kustom .
ALPHA
,BETA
dllKemudian periksa dengan kondisi kompilasi seperti ini:
sumber
Tidak ada preprosesor Swift. (Untuk satu hal, penggantian kode arbitrer merusak jenis dan keamanan memori.)
Swift memang menyertakan opsi konfigurasi build-time, jadi Anda dapat memasukkan kode untuk platform tertentu atau membangun gaya secara kondisional atau sebagai respons terhadap flag yang Anda tentukan dengan
-D
arg compiler. Namun, tidak seperti C, bagian kode Anda yang dikondisikan secara kondisional harus lengkap secara sintaksis. Ada bagian tentang ini di Menggunakan Swift With Cocoa dan Objective-C .Sebagai contoh:
sumber
INT_CONST
mana saja danfloat
diterima. Swift tidak akan mengizinkan ini. Juga, jika Anda bisa melakukanvar floatVal = INT_CONST
itu pasti akan rusak di suatu tempat nanti ketika kompiler mengharapkanInt
tetapi Anda menggunakannya sebagaiFloat
(tipefloatVal
akan disimpulkan sebagaiInt
). 10 gips kemudian dan itu hanya pembersih untuk menghapus makro ...Dua sen saya untuk Xcode 8:
a) Bendera khusus menggunakan
-D
awalan berfungsi dengan baik, tetapi ...b) Penggunaan yang lebih sederhana:
Di Xcode 8 ada bagian baru: "Kondisi Kompilasi Aktif", sudah dengan dua baris, untuk debug dan rilis.
Cukup tambahkan definisi Anda TANPA
-D
.sumber
-D
.isDebug Constant Berdasarkan Kondisi Kompilasi Aktif
Solusi lain, yang mungkin lebih sederhana, yang masih menghasilkan boolean yang dapat Anda gunakan menjadi fungsi tanpa menyertakan
#if
persyaratan di seluruh basis kode Anda adalah mendefinisikanDEBUG
sebagai salah satu target membangun proyek AndaActive Compilation Conditions
dan memasukkan yang berikut (saya mendefinisikannya sebagai konstanta global):isDebug Constant Berdasarkan pada Pengaturan Optimalisasi Kompiler
Konsep ini dibangun berdasarkan jawaban kennytm
Keuntungan utama ketika membandingkan dengan kennytm, adalah bahwa ini tidak bergantung pada metode pribadi atau tidak berdokumen.
Dalam Swift 4 :
Dibandingkan dengan macro preprocessor dan jawaban kennytm ,
-D DEBUG
bendera khusus untuk menggunakannya✓ Didokumentasikan , yang artinya fungsi akan mengikuti pola pelepasan / penghentian API yang normal.
✓ Menggunakan in jika / tidak akan menghasilkan peringatan "Tidak akan pernah dieksekusi".
sumber
Orang Moigna menjawab di sini berfungsi dengan baik. Ini adalah satu lagi kedamaian info jika itu membantu,
Anda dapat meniadakan makro seperti di bawah ini,
sumber
Dalam proyek Swift yang dibuat dengan Xcode Versi 9.4.1, Swift 4.1
bekerja secara default karena dalam Preprocessor Macros DEBUG = 1 telah ditetapkan oleh Xcode.
Jadi, Anda dapat menggunakan #jika DEBUG "di luar kotak".
Ngomong-ngomong, bagaimana cara menggunakan blok kompilasi kondisi secara umum ditulis dalam buku Apple The Swift Programming Language 4.1 (bagian Pernyataan Kontrol Kompiler) dan bagaimana menulis flag kompilasi dan apa yang merupakan rekan dari makro C di Swift ditulis dalam buku Apple lainnya Menggunakan Swift dengan Kakao dan Sasaran C (di bagian Petunjuk Pengolah)
Harapan di masa depan Apple akan menulis konten yang lebih rinci dan indeks untuk buku-buku mereka.
sumber
XCODE 9 DAN DI ATAS
sumber
Setelah mengatur
DEBUG=1
diGCC_PREPROCESSOR_DEFINITIONS
Pengaturan Bangun saya, saya lebih suka menggunakan fungsi untuk melakukan panggilan ini:Dan kemudian cukup lampirkan dalam fungsi ini setiap blok yang ingin saya hilangkan di Debug builds:
Keuntungannya jika dibandingkan dengan:
Apakah kompiler memeriksa sintaks kode saya, jadi saya yakin sintaksnya benar dan dibangun.
sumber
! [Di Xcode 8 & di atas pergi ke pengaturan build -> cari flag kustom] 1
Dalam kode
sumber
Sumber
sumber
@inlinable
di depanfunc
dan ini akan menjadi cara yang paling elegan dan idiomatis untuk Swift. Dalam rilis build,code()
blok Anda akan dioptimalkan dan dihilangkan sama sekali. Fungsi serupa digunakan dalam kerangka NIO Apple sendiri.Ini didasarkan pada jawaban Jon Willis yang bergantung pada tegas, yang hanya dieksekusi dalam kompilasi Debug:
Kasus penggunaan saya adalah untuk mencatat pernyataan cetak. Berikut ini adalah patokan untuk versi Rilis di iPhone X:
cetakan:
Sepertinya Swift 4 sepenuhnya menghilangkan pemanggilan fungsi.
sumber