Dengan tidak adanya macro preprocessor, apakah ada cara untuk mendefinisikan flag khusus skema praktis di tingkat proyek dalam proyek Xcode

174

Sebelum cepat saya akan mendefinisikan satu set skema untuk membangun alpha, beta, dan distribusi. Masing-masing skema ini akan memiliki satu set makro yang didefinisikan untuk gerbang perilaku tertentu di tingkat proyek. Contoh paling sederhana adalah DEBUG = 1 makro yang ditentukan secara default untuk semua proyek Xcode dalam skema default untuk Run build. Orang dapat meminta #jika DEBUG ... dan membuat keputusan dalam kode yang sesuai, bahkan mengumpulkan kode yang tidak perlu.

Tampaknya jenis konfigurasi gating ini tidak semudah menggunakan swift, karena makro tidak didukung. Adakah yang bisa menyarankan pendekatan yang sebanding, saya tidak peduli jika kode tersebut dikompilasi, per se. Saya ingin mem-gerbang fitur berdasarkan skema bangun.

banDedo
sumber

Jawaban:

468

Di Swift Anda masih dapat menggunakan macro preprocessor "# if / # else / # endif" (meskipun lebih terbatas), sesuai dengan dokumen Apple . Ini sebuah contoh:

#if DEBUG
    let a = 2
#else
    let a = 3
#endif

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 DEBUGentri.

(Pengaturan Bangun -> Penyusun Cepat - Bendera Kustom) masukkan deskripsi gambar di sini

Seperti biasa, Anda dapat mengatur nilai yang berbeda saat di Debug atau saat di Rilis.

Saya mengujinya dalam kode nyata; sepertinya tidak dikenali di taman bermain.

Jean Le Moignan
sumber
5
Perhatikan bahwa Anda juga dapat menggunakan baris #elseif untuk menambahkan lebih banyak tes. Cukup menarik, Anda dapat mengakses definisi tetapi tidak mengambil apa-apa darinya; yaitu, define -DDEBUG = 5 (atau = "FOO"), dan kemudian coba cetak dengan "println (DEBUG is (DEBUG)". Baris itu tidak menghasilkan kesalahan, tetapi tidak melakukan apa-apa.
David H
10
Catatan: "Pengaturan Buatan -> Penyusun Swift -> Bendera Kustom" tidak terlihat di pengaturan bangunan "Dasar". Harus memperlihatkan "Semua" pengaturan bangunan agar dapat muncul.
levibostian
7
@EugeneDubinin mungkin karena Anda harus memastikan yang $(inherited)digunakan dalam pengaturan target untuk mewarisi pengaturan proyek.
DanSkeel
2
@DanSkeel tangkapan yang bagus, menambahkan $(inherited)membuat komentar saya tidak relevan, terima kasih!
Yevhen Dubinin
10
Di Xcode 8 sekarang ada juga pengaturan "Kondisi Kompilasi Aktif" di bagian "Swift Compiler - Custom Flags". Anda dapat menambahkan bendera di sini tanpa perlu -D
Marcus
32

Kami mengalami masalah dengan tidak ingin menetapkan flag compiler swift karena kami tidak ingin harus mengaturnya dan tetap memperbaruinya untuk target yang berbeda dll. Juga, dalam basis kode campuran kami, kami tidak ingin mengingat untuk mengatur bendera kami secara tepat setiap waktu untuk setiap bahasa.

Untuk kami, kami mendeklarasikan file di ObjC

PreProcessorMacros.h

extern BOOL const DEBUG_BUILD;

Dalam .m

PreProcessorMacros.m

#ifdef DEBUG
    BOOL const DEBUG_BUILD = YES;
#else
    BOOL const DEBUG_BUILD = NO;
#endif

Kemudian, di Header Bridging Objective-C Anda

#import "PreProcessorMacros.h"

Sekarang, gunakan ini di basis kode Swift Anda

if DEBUG_BUILD {
    println("debug")
} else {
    println("release")
}

Ini jelas merupakan solusi, tetapi itu memecahkan masalah kami jadi saya mempostingnya di sini dengan harapan itu akan membantu. Ini tidak dimaksudkan untuk menyarankan bahwa jawaban yang ada tidak valid.

Logan
sumber
11
Inti dari makro adalah mengubah kode berdasarkan konfigurasi build. Anda membawa if kembali ke runtime, Anda tidak perlu makro untuk itu.
Berik
18
@Berik - Saya memposting solusi yang valid dengan harapan itu juga dapat membantu orang lain yang mencoba untuk menyelesaikan aspek dari masalah ini, terutama dalam proyek multi-bahasa. Jika masalah Anda tidak memerlukan kompilasi kode khusus itu baik-baik saja. Juga komentar baik-baik saja, terutama ketika mendidik beberapa alasan mengapa ini mungkin bukan solusi bagi mereka. Juga meminta untuk membuat catatan dalam jawaban tentang keterbatasan pendekatan ini. Downvoting tidak perlu dan menghambat solusi alternatif yang mungkin bisa membantu orang lain memecahkan masalah yang sama. Juga, op mengatakan "Saya tidak peduli jika kode ini dikompilasi".
Logan
5

Solusi yang lebih cepat untuk metode Logans. Set -D DEBUGdi Other Swift Flagsdari Swift Compiler - Custom Flagsbagian dalam pengaturan membangun dari target Anda.

Kemudian nyatakan metode berikut dalam lingkup global:

#if DEBUG
let isDebugMode = true
#else
let isDebugMode = false
#endif

Sekarang gunakan sebagai

if isDebugMode {
    // Do debug stuff
}
Sahil Kapoor
sumber
1

Bagi saya, setel item debug " Kondisi Kompilasi Aktif " ke "DEBUG" berfungsi.

Kemudian menggunakan kerja kunci DEBGU di #Jika DEBUG bekerja dalam mode debug dan #ELSE dalam mode rilis:

  1. Pilih target Anda,
  2. Dalam pencarian Bangun Pengaturan tab untuk "Kondisi Kompilasi Aktif",
  3. Atur nilai item "Debug" -nya ke "YourKeyWord",
  4. Gunakan hanya sebagai berikut:

    #if DEBUG
        print("You'r running in DEBUG mode!")
    #else
        print("You'r running in RELEASE mode!")
    #endif
Marjan Basiri
sumber
0

Saya bekerja di basis kode bahasa campuran di mana kode obj-c menggunakan makro untuk mengirim pesan debug ke konsol (dan makro itu bergantung pada flag preprocessor debug kami). Saya ingin dapat memanggil makro yang sama dalam kode cepat ...

  1. Saya membuat metode kelas pada salah satu kelas obj-c saya yang merupakan pembungkus makro itu.
  2. Saya menambahkan header obj-c ke file header jembatan kami.
  3. Sekarang kode cepat saya memanggil metode kelas itu sebagai "proxy" ke makro obj-c.

Agak menyebalkan bahwa saya tidak bisa memanggil makro langsung ke atas di kode cepat, tapi setidaknya sekarang saya hanya punya satu tempat di proyek untuk khawatir mengaktifkan / menonaktifkan flag debug saya.

ghostatron
sumber