In assenza di macro preprocessore, esiste un modo per definire flag pratici specifici dello schema a livello di progetto nel progetto Xcode


174

Prima di un rapido definirei una serie di schemi per build alfa, beta e di distribuzione. Ognuno di questi schemi avrebbe una serie di macro definite per bloccare determinati comportamenti a livello di progetto. L'esempio più semplice è la macro DEBUG = 1 definita per impostazione predefinita per tutti i progetti Xcode nello schema predefinito per la build Run. Si potrebbe interrogare #ifdef DEBUG ... e prendere le decisioni nel codice di conseguenza, anche compilando il codice non necessario.

Sembra che questo tipo di gating configurazionale non sia facile usando swift, poiché le macro non sono supportate. Qualcuno può suggerire un approccio comparabile, non mi interessa se il codice è compilato, di per sé. Vorrei però trasferire le funzionalità in base allo schema di creazione.

Risposte:


468

In Swift puoi comunque utilizzare le macro del preprocessore "# if / # else / # endif" (anche se più vincolate), secondo i documenti Apple . Ecco un esempio:

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

Ora, però, è necessario impostare il simbolo "DEBUG" altrove. Impostalo nella sezione "Compilatore Swift - Bandiere personalizzate", riga "Altre bandiere Swift". Aggiungi il simbolo DEBUG con la -D DEBUGvoce.

(Impostazioni build -> Compilatore Swift - Flag personalizzati) inserisci qui la descrizione dell'immagine

Come al solito, è possibile impostare un valore diverso in Debug o in Release.

L'ho provato in codice reale; non sembra essere riconosciuto in un parco giochi.


5
Nota che puoi anche usare le righe #elseif per aggiungere altri test. È interessante notare che è possibile accedere alla definizione ma non estrarre nulla da essa; cioè, definire -DDEBUG = 5 (o = "FOO"), quindi provare a stamparlo con "println (DEBUG è (DEBUG)". Quella riga non genera errori, ma non fa nulla.
David H

10
Nota: "Impostazioni predefinite -> Compilatore rapido -> Flag personalizzati" non visibile nelle impostazioni di compilazione "Base". Deve mostrare le impostazioni di compilazione "Tutto" affinché appaia.
levibostiano,

7
@EugeneDubinin probabilmente perché dovresti assicurarti che $(inherited)venga usato nelle impostazioni di destinazione per ereditare le impostazioni del progetto.
DanSkeel,

2
@DanSkeel bella cattura, l'aggiunta $(inherited)rende il mio commento irrilevante, grazie!
Yevhen Dubinin,

10
In Xcode 8 ora esiste anche un'impostazione "Condizioni di compilazione attive" nella sezione "Compilatore Swift - Bandiere personalizzate". Puoi aggiungere bandiere qui senza bisogno del MrGreen
Marcus

32

Abbiamo riscontrato un problema con la mancata impostazione di flag di compilazione rapidi perché non volevamo impostarli e tenerli aggiornati per target diversi, ecc. Inoltre, nella nostra base di codici misti, non volevamo ricordare per impostare le nostre bandiere in modo appropriato tutto il tempo per ogni lingua.

Per il nostro, abbiamo dichiarato un file in ObjC

PreProcessorMacros.h

extern BOOL const DEBUG_BUILD;

In loro

PreProcessorMacros.m

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

Quindi, nella tua intestazione ponte Objective-C

#import "PreProcessorMacros.h"

Ora, usa questo nella tua base di codice Swift

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

Questa è sicuramente una soluzione alternativa, ma ha risolto il nostro problema, quindi l'ho pubblicato qui nella speranza che possa aiutare. Non intende suggerire che le risposte esistenti non sono valide.


11
Il punto centrale delle macro è cambiare il codice in base alla configurazione della build. Stai riportando il if al runtime, non hai bisogno di macro per quello.
Berik,

18
@Berik - Ho pubblicato una soluzione valida nella speranza che possa anche aiutare gli altri a cercare di risolvere un aspetto di questo problema, in particolare nei progetti multilingue. Se il tuo problema non richiede la compilazione di codice specifico, va bene. Anche un commento va bene, in particolare quando educa alcuni perché questa potrebbe non essere la soluzione per loro. Chiedere anche di prendere nota nella risposta sui limiti di questo approccio. Il downvoting non è necessario e scoraggia soluzioni alternative che potrebbero essere utili ad altri per risolvere problemi simili. Inoltre, op dice "Non mi interessa se il codice è compilato".
Logan,

5

Soluzione più rapida al metodo Logans. Set -D DEBUGin Other Swift Flagsdi Swift Compiler - Custom Flagssezione impostazioni di generazione del vostro target.

Quindi dichiarare il seguente metodo nell'ambito globale:

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

Ora usalo come

if isDebugMode {
    // Do debug stuff
}

1

Per me, impostare l'elemento di debug di " Condizione di compilazione attiva " su "DEBUG" ha funzionato.

Quindi l'utilizzo della chiave DEBGU funziona in #IF DEBUG funziona in modalità debug e #ELSE in modalità di rilascio:

  1. Seleziona il tuo obiettivo,
  2. Nella scheda Impostazioni build cerca "Condizione di compilazione attiva",
  3. Imposta il valore dell'elemento "Debug" su "YourKeyWord",
  4. Utilizzare semplicemente come segue:

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

0

Sto lavorando in una base di codice in linguaggio misto in cui il codice obj-c utilizza una macro per inviare messaggi di debug alla console (e quella macro si basa sul nostro flag di preprocessore di debug). Volevo essere in grado di chiamare quella stessa macro nel codice rapido ...

  1. Ho creato un metodo di classe su una delle mie classi obj-c che è un wrapper per quella macro.
  2. Ho aggiunto quell'intestazione obj-c al nostro file di intestazione bridge.
  3. Ora il mio codice rapido chiama quel metodo di classe come "proxy" per la macro obj-c.

È leggermente fastidioso che non riesco a chiamare la macro direttamente nel codice rapido, ma almeno ora ho solo un posto nel progetto di cui preoccuparmi di attivare / disattivare la mia bandiera di debug.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.