Wenn keine Präprozessor-Makros vorhanden sind, gibt es eine Möglichkeit, praktische schemaspezifische Flags auf Projektebene im Xcode-Projekt zu definieren

174

Bevor ich schnell war, würde ich eine Reihe von Schemata für Alpha-, Beta- und Distributions-Builds definieren. Jedes dieser Schemata verfügt über eine Reihe von Makros, die definiert wurden, um bestimmte Verhaltensweisen auf Projektebene zu steuern. Das einfachste Beispiel ist das Makro DEBUG = 1, das standardmäßig für alle Xcode-Projekte im Standardschema für den Build-Build definiert ist. Man könnte #ifdef DEBUG abfragen ... und Entscheidungen im Code entsprechend treffen, sogar nicht benötigten Code kompilieren.

Es scheint, dass diese Art der Konfigurationssteuerung mit Swift nicht so einfach ist, da Makros nicht unterstützt werden. Kann jemand einen vergleichbaren Ansatz vorschlagen, ist es mir egal, ob der Code per se kompiliert wird. Ich möchte jedoch Features basierend auf dem Build-Schema testen.

banDedo
quelle

Antworten:

468

In Swift können Sie weiterhin die Präprozessor-Makros "# if / # else / # endif" verwenden (obwohl eingeschränkter), wie in den Apple-Dokumenten beschrieben . Hier ist ein Beispiel:

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

Jetzt müssen Sie das Symbol "DEBUG" jedoch an einer anderen Stelle setzen. Stellen Sie es im Abschnitt "Swift Compiler - Benutzerdefinierte Flags" in der Zeile "Andere Swift Flags" ein. Sie fügen dem -D DEBUGEintrag das DEBUG-Symbol hinzu .

(Build-Einstellungen -> Swift Compiler - Benutzerdefinierte Flags) Geben Sie hier die Bildbeschreibung ein

Wie üblich können Sie im Debug oder im Release einen anderen Wert festlegen.

Ich habe es in echtem Code getestet. es scheint auf einem Spielplatz nicht erkannt zu werden.

Jean Le Moignan
quelle
5
Beachten Sie, dass Sie auch # elseif-Zeilen verwenden können, um weitere Tests hinzuzufügen. Interessanterweise können Sie auf die Definition zugreifen, aber nichts daraus extrahieren. Definieren Sie also -DDEBUG = 5 (oder = "FOO") und versuchen Sie dann, es mit "println (DEBUG is (DEBUG)" zu drucken. Diese Zeile generiert keine Fehler, führt aber nichts aus.
David H
10
Hinweis: "Built Settings -> Swift Compiler -> Custom Flags" ist in den Build-Einstellungen "Basic" nicht sichtbar. Es müssen "Alle" Build-Einstellungen angezeigt werden, damit es angezeigt wird.
Levibostian
7
@EugeneDubinin wahrscheinlich, weil Sie sicherstellen sollten, dass $(inherited)in den Zieleinstellungen verwendet wird, um Projekteinstellungen zu erben.
DanSkeel
2
@ DanSkeel schöner Fang, das Hinzufügen $(inherited)macht meinen Kommentar irrelevant, danke!
Yevhen Dubinin
10
In Xcode 8 gibt es jetzt auch eine Einstellung "Active Compilation Conditions" im Abschnitt "Swift Compiler - Custom Flags". Sie können hier Flaggen hinzufügen, ohne die -D
Marcus
32

Wir hatten ein Problem damit, dass wir keine schnellen Compiler-Flags setzen wollten, weil wir sie nicht setzen und für verschiedene Ziele usw. auf dem neuesten Stand halten wollten. Außerdem wollten wir uns in unserer gemischten Codebasis nicht daran erinnern um unsere Flaggen für jede Sprache jederzeit angemessen zu setzen.

Für uns haben wir eine Datei in ObjC deklariert

PreProcessorMacros.h

extern BOOL const DEBUG_BUILD;

In ihnen

PreProcessorMacros.m

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

Dann in Ihrem Objective-C-Bridging-Header

#import "PreProcessorMacros.h"

Verwenden Sie dies jetzt in Ihrer Swift-Codebasis

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

Dies ist definitiv eine Problemumgehung, aber es hat unser Problem gelöst, also habe ich es hier veröffentlicht, in der Hoffnung, dass es helfen wird. Es soll nicht bedeuten, dass die vorhandenen Antworten ungültig sind.

Logan
quelle
11
Der springende Punkt bei Makros ist, den Code basierend auf der Build-Konfiguration zu ändern. Sie bringen das if wieder zur Laufzeit, dafür benötigen Sie keine Makros.
Berik
18
@Berik - Ich habe eine gültige Lösung veröffentlicht, in der Hoffnung, dass sie auch anderen helfen könnte, einen Aspekt dieses Problems zu lösen, insbesondere in mehrsprachigen Projekten. Wenn für Ihr Problem kein spezifischer Code kompiliert werden muss, ist dies in Ordnung. Auch ein Kommentar ist in Ordnung, insbesondere wenn er einige aufklärt, warum dies möglicherweise nicht die Lösung für sie ist. Bitten Sie auch darum, in der Antwort eine Notiz über die Einschränkungen dieses Ansatzes zu machen. Ein Downvoting ist nicht erforderlich und rät von alternativen Lösungen ab, die für andere hilfreich sein könnten, um ähnliche Probleme zu lösen. Außerdem sagt op "Es ist mir egal, ob der Code kompiliert ist".
Logan
5

Schnellere Lösung für die Logans-Methode. Stellen Sie -D DEBUGin Other Swift Flagsdem Swift Compiler - Custom FlagsAbschnitt in Build - Einstellungen Ihres Ziels.

Deklarieren Sie dann die folgende Methode im globalen Bereich:

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

Verwenden Sie es jetzt als

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

Setzen Sie für mich das Debug-Element " Active Compilation Condition " auf "DEBUG".

Dann funktioniert die Verwendung der DEBGU-Schlüsselarbeit in #IF DEBUG im Debug-Modus und #ELSE im Release-Modus:

  1. Wählen Sie Ihr Ziel,
  2. Suchen Sie auf der Registerkarte "Build-Einstellungen" nach "Active Compilation Condition".
  3. Setzen Sie den Wert des Elements "Debug" auf "YourKeyWord".
  4. Verwenden Sie einfach wie folgt:

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

Ich arbeite in einer gemischten Codebasis, in der der obj-c-Code ein Makro verwendet, um Debug-Nachrichten an die Konsole zu senden (und dieses Makro basiert auf unserem Debug-Präprozessor-Flag). Ich wollte in der Lage sein, dasselbe Makro im schnellen Code aufzurufen ...

  1. Ich habe eine Klassenmethode für eine meiner obj-c-Klassen erstellt, die einen Wrapper um dieses Makro darstellt.
  2. Ich habe diesen obj-c-Header zu unserer Bridge-Header-Datei hinzugefügt.
  3. Jetzt ruft mein schneller Code diese Klassenmethode als "Proxy" für das obj-c-Makro auf.

Es ist leicht ärgerlich, dass ich das Makro nicht einfach direkt im schnellen Code aufrufen kann, aber zumindest habe ich jetzt nur einen Platz im Projekt, an dem ich mir Sorgen machen muss, ob ich mein Debug-Flag ein- oder ausschalten soll.

Ghostatron
quelle