Swift: Wie verwende ich PREPROCESSOR Flags (wie `#if DEBUG`), um API-Schlüssel zu implementieren?

92

In Objective-Cwar es manchmal nützlich statische String - Konstanten zu verwenden alternative API Schlüssel definieren (beispielsweise zur Unterscheidung zwischen RELEASE und DEBUG Schlüssel für die Analytik von Paketen wie MixPanel, Flurry oder Crashlytics):

#if DEBUG
static NSString *const API_KEY = @"KEY_A";
#else
static NSString *const API_KEY = @"KEY_B";
#endif

und dann...

[Analytics startSession:API_KEY];

Wie übersetzt sich dies in Swift, da der Swift-Compiler keinen Präprozessor mehr verwendet?

Cleverbit
quelle

Antworten:

157

Apple bietet ab Xcode 8 volle Unterstützung für Swift-Präprozessor-Flags , sodass diese Werte nicht mehr unter "Andere Swift-Flags" festgelegt werden müssen.

Die neue Einstellung heißt "Active Compilation Conditions" (Aktive Kompilierungsbedingungen) und bietet Unterstützung auf höchster Ebene für das Swift-Äquivalent von Präprozessor-Flags. Sie verwenden es genauso wie "Other Swift Flags", außer dass Sie dem Wert kein "-D" voranstellen müssen (es ist also nur ein wenig sauberer).

Aus den Xcode 8-Versionshinweisen :

Active Compilation Conditionsist eine neue Build-Einstellung zum Übergeben von bedingten Kompilierungsflags an den Swift-Compiler. Jedes Element des Werts dieser Einstellung wird an swiftc übergeben, dem -D vorangestellt ist , genauso wie Elemente von Preprocessor Macrospass mit demselben Präfix klirren . (22457329)

Geben Sie hier die Bildbeschreibung ein

Sie verwenden die obige Einstellung wie folgt:

#if DEBUG
    let accessToken = "DebugAccessToken"
#else
    let accessToken = "ProductionAccessToken"
#endif
Dan Loewenherz
quelle
2
Hinweis: Sie sollten nicht = 1 oder einen anderen = Wert angeben. Vielmehr müssen Sie nur den Flaggennamen angeben. :]
JRG-Entwickler
@ JRG-Developer Ich bin nicht anderer Meinung, aber ich bin nicht sicher, wie Ihr Kommentar hier gilt.
Dan Loewenherz
9
Dies ist eine hilfreiche Antwort, aber da ich einen Objective-C-Hintergrund habe (wie ich mir viele iOS-Entwickler vorstelle), habe ich angenommen, dass ich angeben muss =1... Ich habe ein bisschen Zeit verloren, um herauszufinden, warum es nicht funktioniert als ich es tat. Also dachte ich, ich würde diesen Leckerbissen teilen, um dem nächsten Kerl zu helfen. :] Trotzdem danke für deine Antwort hier!
JRG-Entwickler
1
@ JRG-Developer, @Dan Loewenherz Ich habe sowohl DEBUGin Active Compilation Conditionsals auch DEBUG=1in gesetzt Preprocessor Macrosund diese Konfiguration funktioniert überhaupt nicht. Soll ich entfernen DEBUG=1? Aus den obigen Kommentaren nicht klar.
Bhavin_m
2
@ DanLoewenherz Du hast absolut recht. Ich hatte in meinen Zieleinstellungen "DEBUG" für die Archivkonfiguration festgelegt, sodass jedes Mal eine Debug-Anweisung ausgeführt wird und niemals die Freigabebedingung ausgeführt wird. Wenn Sie vor einem Problem stehen, überprüfen Sie bitte zuerst das Ziel Build Configuration. Überprüfen Sie diese Antwort stackoverflow.com/questions/9063100/… für weitere Informationen.
Bhavin_m
130

AKTUALISIERT: Xcode 8 unterstützt dies jetzt automatisch, siehe Antwort von @ DanLoewenherz oben.

Vor Xcode 8 konnten Sie Makros noch auf die gleiche Weise verwenden:

#if DEBUG
let apiKey = "KEY_A"
#else
let apiKey = "KEY_B"
#endif

Damit sie jedoch von Swift aufgenommen werden können, müssen Sie in den Build-Einstellungen Ihres Ziels "Andere Swift-Flags" festlegen:

  • Öffnen Sie die Build-Einstellungen für Ihr Ziel
  • Suche nach "anderen schnellen Flaggen"
  • Fügen Sie die gewünschten Makros hinzu, denen das -DFlag vorangestellt ist

Geben Sie hier die Bildbeschreibung ein

Cleverbit
quelle
du hast meinen Tag gerettet! für mich Es hat nicht ohne -DPräfix
funktioniert
5

Versuchen Sie als Folgebeobachtung, API-Schlüssel / Geheimnisse nicht im Klartext im Repository zu speichern. Verwenden Sie ein Geheimnisverwaltungssystem, um die Schlüssel / Geheimnisse in die Umgebungsvariablen des Benutzers zu laden. Andernfalls ist Schritt 1 erforderlich, falls akzeptabel.

  1. Legen Sie die "Geheimnisse" in eine Klartextdatei oben im beiliegenden Repository
  2. Erstellen Sie eine ../set_keys.shListe mit export API_KEY_A='<plaintext_key_aef94c5l6>'(verwenden Sie ein einfaches Anführungszeichen, um eine Bewertung zu verhindern)
  3. Fügen Sie eine Run-Skriptphase hinzu, die dies kann, source ../set_keys.shund verschieben Sie sie an den Anfang der Ausführungsreihenfolge
  4. Fügen Sie unter Build-Einstellungen> Präprozessor-Makros nach Bedarf Definitionen hinzu, z API_KEY_A="$API_KEY_A"

Dadurch wird die Umgebungsvariable in der Compiler-Definition erfasst, die später bei jedem Clang-Aufruf für jede Quelldatei verwendet wird.

Beispiel Verzeichnisstruktur

[10:33:15] ~/code/memo yes? tree -L 2 .
.
├── Memo
│   ├── Memo
│   ├── Memo.xcodeproj
│   ├── Memo.xcworkspace
│   ├── Podfile
│   ├── Podfile.lock
│   └── Pods
└── keys
Michael Lorenzo
quelle
0

In schnellen Paketen müssen Sie dies innerhalb des swiftSettingsArguments .targetin Ihrer Package.swiftDatei tun . Verwenden Sie die defineMethode (Apple-Dokumentation) oder die Swift-Dokumentation

targets: [
.target(name: String,
            dependencies: [Target.Dependency],
            path: String?,
            exclude: [String]?,
            sources: [String]?,,
            cSettings: [CSetting]?,
            cxxSettings: [CXXSetting]?,
            swiftSettings: [SwiftSetting]?,
            linkerSettings: [LinkerSetting]?),

Meins sieht so aus und es funktioniert!

            swiftSettings: [
               .define("VAPOR")
            ]

In meinem Code kann ich unter bestimmten Bedingungen kompilieren:

#if VAPOR
Garafajon
quelle