/ / #ifdef náhrada v jazyku Swift - swift, xcode, preprocesor, preprocesor-smernica

#ifdef nahradenie v jazyku Swift - swift, xcode, preprocesor, direktíva preprocesora

V C / C ++ / Objective-C môžete definovať makro pomocou preprocesorov kompilátora. Navyše môžete zahrnúť / vylúčiť niektoré časti kódu pomocou preprocesorov kompilátora.

#ifdef DEBUG
// Debug-only code
#endif

Existuje podobné riešenie v Swifte?

odpovede:

857 za odpoveď č. 1

Áno, môžete to urobiť.

V Swifte môžete stále používať preprocesorové makra „# if / # else / # endif“ (aj keď sú viac obmedzené) podľa Apple docs, Tu je príklad:

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

Teraz však musíte nastaviť symbol „DEBUG“ inde. Nastavte ho v časti „Kompilátor Swift - Vlastné vlajky“, riadok „Ostatné vlajky Swift“. Symbol DEBUG pridáte pomocou -D DEBUG entry.

Ako obvykle môžete nastaviť inú hodnotu pri ladení alebo pri vydaní.

Testoval som to v reálnom kóde a funguje to; nezdá sa, že by to bolo rozpoznané na detskom ihrisku.

Môžete si prečítať môj pôvodný príspevok tu.


DÔLEŽITÁ POZNÁMKA: -DDEBUG=1 nefunguje. Iba -D DEBUG Tvorba. Zdá sa, že kompilátor ignoruje príznak s konkrétnou hodnotou.


286 pre odpoveď č. 2

Ako sa uvádza v Apple Docs

Kompilátor Swift neobsahuje apreprocesor. Namiesto toho využíva atribúty času kompilácie, zostavenie konfigurácií a jazykové funkcie na dosiahnutie rovnakej funkcie. Z tohto dôvodu sa direktívy preprocesora do aplikácie Swift neimportujú.

Podarilo sa mi dosiahnuť to, čo som chcel, pomocou vlastných konfigurácií zostavy:

  1. Prejdite do svojho projektu / vyberte cieľ / Nastavenia zostavy / vyhľadajte Vlastné vlajky
  2. Pre svoj zvolený cieľ nastavte svoj vlastný príznak pomocou prefixu -D (bez medzier), pre Debug aj Release
  3. Vyššie uvedené kroky urobte pre každý cieľ, ktorý máte

Takto skontrolujete cieľ:

#if BANANA
print("We have a banana")
#elseif MELONA
print("Melona")
#else
print("Kiwi")
#endif

tu zadajte popis obrázku

Testované pomocou Swift 2.2


145 za odpoveď č. 3

V mnohých situáciách naozaj nepotrebujete podmienečné podmienky zostavenie; len treba podmienene správanie že môžete zapnúť a vypnúť. Na to môžete použiť premennú prostredia. To má obrovskú výhodu, že v skutočnosti nemusíte prekompilovať.

Premennú prostredia môžete nastaviť a ľahko zapnúť alebo vypnúť v editore schém:

tu zadajte popis obrázku

Premennú prostredia môžete načítať pomocou NSProcessInfo:

    let dic = NSProcessInfo.processInfo().environment
if dic["TRIPLE"] != nil {
// ... do secret stuff here ...
}

Tu je príklad zo skutočného života.Moja aplikácia je spustená iba na zariadení, pretože využíva hudobnú knižnicu, ktorá v Simulátore neexistuje. Ako potom na Simulátore snímať obrazovky na zariadeniach, ktoré nevlastním? Bez týchto snímok obrazovky nemôžem odoslať do AppStore.

potrebujem falošné údaje a a iný spôsob jeho spracovania. Mám dve premenné prostredia:ten, ktorý po zapnutí povie aplikácii, aby generovala falošné údaje zo skutočných údajov, keď je spustená v mojom zariadení; druhá, ktorá po zapnutí používa falošné údaje (nie chýbajúcu hudobnú knižnicu), keď je spustená na simulátore. Zapnutie a vypnutie každého z týchto špeciálnych režimov je jednoduché vďaka začiarkavacím políčkam premenných prostredia v editore schém. A bonusom je, že ich „nemôžem náhodne použiť v mojej zostave App Store, pretože archivácia nemá žiadne premenné prostredia.


119 pre odpoveď č. 4

Zásadná zmena ifdef náhrada prišla s Xcode 8. teda použitie Podmienky aktívneho zostavenia.

Odkazujú na Budovanie a prepájanie v Xcode 8 Poznámka k vydaniu.

Nové nastavenie zostavy

Nové nastavenie: SWIFT_ACTIVE_COMPILATION_CONDITIONS

“Active Compilation Conditions” is a new build setting for passing conditional compilation flags to the Swift compiler.

Predtým sme museli deklarovať vaše príznaky podmienenej kompilácie pod OTHER_SWIFT_FLAGS, pričom sme nezabudli pred nastavenie pridať „-D“. Napríklad na podmienenú kompiláciu s hodnotou MYFLAG:

#if MYFLAG1
// stuff 1
#elseif MYFLAG2
// stuff 2
#else
// stuff 3
#endif

Hodnota, ktorá sa má pridať k nastaveniu -DMYFLAG

Teraz už stačí iba odovzdať hodnotu MYFLAG do nového nastavenia. Je čas presunúť všetky tieto podmienené hodnoty kompilácie!

Ďalšie funkcie Swift Build Settings v Xcode 8 nájdete na nasledujúcom odkaze: http://www.miqu.me/blog/2016/07/31/xcode-8-new-build-settings-and-analyzer-improvements/


73 pre odpoveď № 5

Od verzie Swift 4.1, ak potrebujete iba skontrolovať, či je kód zostavený s konfiguráciou ladenia alebo vydania, môžete použiť vstavané funkcie:

  • _isDebugAssertConfiguration() (pravda, keď je optimalizácia nastavená na -Onone)
  • _isReleaseAssertConfiguration() (pravda, keď je optimalizácia nastavená na -O) (nie je k dispozícii pre Swift 3+)
  • _isFastAssertConfiguration() (pravda, keď je optimalizácia nastavená na -Ounchecked)

napr.

func obtain() -> AbstractThing {
if _isDebugAssertConfiguration() {
return DecoratedThingWithDebugInformation(Thing())
} else {
return Thing()
}
}

V porovnaní s makrami predprocesora

  • ✓ Nemusíte definovať zvyk -D DEBUG príznak použiť
  • ~ Je to vlastne definované z hľadiska nastavení optimalizácie, nie konfigurácie zostavenia Xcode
  • ✗ Nedokumentované, čo znamená, že túto funkciu je možné odstrániť v ktorejkoľvek aktualizácii (mala by však byť bezpečná v obchode AppStore, pretože optimalizátor z nich urobí konštanty).

  • ✗ Použitie príkazu if / else vždy vygeneruje varovanie „Nikdy sa nespustí“.


72 pre odpoveď č. 6

použitie Podmienky aktívneho zostavenia nastavenie v Zostavenie nastavení / kompilátor Swift - vlastné vlajky.

  • Toto je nové nastavenie zostavenia na odovzdávanie príznakov podmienenej kompilácie kompilátoru Swift.
  • Jednoduché pridanie príznakov, ako je tento: ALPHA, BETA atď.

Potom to skontrolujte pomocou podmienky kompilácie ako toto:

#if ALPHA
//
#elseif BETA
//
#else
//
#endif

Tip: Môžete tiež použiť #if !ALPHA atď.


69 pre odpoveď č. 7

Neexistuje preprocesor Swift. (Za prvé, ľubovoľná zámena kódu prerušuje bezpečnosť typu a pamäte.)

Swift však obsahuje možnosti konfigurácie v čase zostavenia, takže môžete podmienečne zahrnúť kód pre určité platformy alebo štýly stavania alebo v reakcii na príznaky, ktoré definujete pomocou -D kompilátor args. Na rozdiel od C však musí byť podmienene skompilovaná časť vášho kódu syntakticky úplná. O tejto téme je časť Používanie Swift s kakaom a Objective-C.

Napríklad:

#if os(iOS)
let color = UIColor.redColor()
#else
let color = NSColor.redColor()
#endif

39 pre odpoveď č. 8

Moje dva centy za Xcode 8:

a) Vlastný príznak pomocou -D predpona funguje dobre, ale ...

b) Jednoduchšie použitie:

V Xcode 8 sa nachádza nová sekcia: „Podmienky aktívnej kompilácie“, už s dvoma riadkami, na ladenie a vydanie.

Jednoducho zadajte svoju definíciu BEZ -D.


24 pre odpoveď č. 9

Konštanta isDebug je založená na podmienkach aktívnej kompilácie

Ďalšie, možno jednoduchšie riešenie, ktoré má stále za následok boolean, ktorý môžete odovzdať do funkcií bez korenia #if podmienkami v celej vašej kódovej základni je definovať DEBUG ako jeden z cieľových cieľov projektu Active Compilation Conditions a zahrnúť nasledujúce (definujem to ako globálnu konštantu):

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

Konštanta isDebug je založená na nastaveniach optimalizácie kompilátora

Tento koncept nadväzuje na kennymova odpoveď

Hlavnou výhodou v porovnaní s kennym je, že sa nespolieha na súkromné ​​alebo neregistrované metódy.

v Swift 4:

let isDebug: Bool = {
var isDebug = false
// function with a side effect and Bool return value that we can pass into assert()
func set(debug: Bool) -> Bool {
isDebug = debug
return isDebug
}
// assert:
// "Condition is only evaluated in playgrounds and -Onone builds."
// so isDebug is never changed to true in Release builds
assert(set(debug: true))
return isDebug
}()

V porovnaní s makrami preprocesora a kennymova odpoveď,

  • ✓ Nemusíte definovať zvyk -D DEBUG príznak použiť
  • ~ Je to vlastne definované z hľadiska nastavení optimalizácie, nie konfigurácie zostavenia Xcode
  • zdokumentované, čo znamená, že funkcia bude postupovať podľa bežných vzorov uvoľňovania / ukončovania podpory API.

  • ✓ Použitie v if / else bude nie vygenerovať varovanie „Nikdy sa nevykoná“.


2 pre odpoveď č. 10

Po nastavení DEBUG=1 vo vašom GCC_PREPROCESSOR_DEFINITIONS Vytváranie nastavení Dávam prednosť použitiu funkcie na uskutočnenie týchto hovorov:

func executeInProduction(_ block: () -> Void)
{
#if !DEBUG
block()
#endif
}

A potom stačí vložiť do tejto funkcie akýkoľvek blok, ktorý chcem vynechať v zostavách Debug:

executeInProduction {
Fabric.with([Crashlytics.self]) // Compiler checks this line even in Debug
}

Výhoda v porovnaní s:

#if !DEBUG
Fabric.with([Crashlytics.self]) // This is not checked, may not compile in non-Debug builds
#endif

Je to tak, že kompilátor kontroluje syntax môjho kódu, takže som si istý, že jeho syntax je správna a zostavená.


1 pre odpoveď č. 11

To stavia na Jon Willis odpoveď, ktorá sa spolieha na tvrdenie, ktoré sa vykoná iba v kompiláciách Debug:

func Log(_ str: String) {
assert(DebugLog(str))
}
func DebugLog(_ str: String) -> Bool {
print(str)
return true
}

Môj prípad použitia je na zaznamenávanie tlačových výpisov. Tu je referenčná hodnota pre verziu Release na iPhone X:

let iterations = 100_000_000
let time1 = CFAbsoluteTimeGetCurrent()
for i in 0 ..< iterations {
Log ("⧉ unarchiveArray:(fileName) memoryTime:(memoryTime) count:(array.count)")
}
var time2 = CFAbsoluteTimeGetCurrent()
print ("Log: (time2-time1)" )

tlačí:

Log: 0.0

Vyzerá to, že Swift 4 úplne vylučuje volanie funkcie.


0 pre odpoveď č. 12

! [V Xcode 8 a vyššie prejdite na nastavenie zostavenia -> vyhľadajte vlastné vlajky ]1

V kóde

 #if Live
print("Live")
#else
print("debug")
#endif