W przypadku braku makr preprocesora, czy istnieje sposób na zdefiniowanie praktycznych flag specyficznych dla schematu na poziomie projektu w projekcie Xcode

174

Przed swiftem zdefiniowałbym zestaw schematów dla wersji alfa, beta i dystrybucji. Każdy z tych schematów miałby zestaw makr, które zostały zdefiniowane w celu bramkowania określonych zachowań na poziomie projektu. Najprostszym przykładem jest makro DEBUG = 1, które jest zdefiniowane domyślnie dla wszystkich projektów Xcode w domyślnym schemacie dla kompilacji Uruchom. Można zapytać #ifdef DEBUG ... i odpowiednio podjąć decyzje w kodzie, nawet kompilując niepotrzebny kod.

Wydaje się, że ten typ bramkowania konfiguracyjnego nie jest tak łatwy w użyciu, jak szybkie, ponieważ makra nie są obsługiwane. Czy ktoś może zaproponować podobne podejście, nie obchodzi mnie, czy kod jest kompilowany jako taki. Chciałbym jednak bramkować funkcje w oparciu o schemat kompilacji.

banDedo
źródło

Odpowiedzi:

468

W Swift możesz nadal używać makr preprocesora „# if / # else / # endif” (chociaż jest to bardziej ograniczone), zgodnie z dokumentacją Apple . Oto przykład:

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

Teraz jednak musisz ustawić symbol „DEBUG” w innym miejscu. Ustaw go w sekcji „Swift Compiler - Custom Flags”, wiersz „Other Swift Flags”. Dodajesz symbol DEBUG do -D DEBUGwpisu.

(Ustawienia kompilacji -> Swift Compiler - Flagi niestandardowe) wprowadź opis obrazu tutaj

Jak zwykle możesz ustawić inną wartość w debugowaniu lub w wersji.

Przetestowałem to w prawdziwym kodzie; nie wydaje się być rozpoznawany na placu zabaw.

Jean Le Moignan
źródło
5
Zauważ, że możesz również użyć linii #elseif, aby dodać więcej testów. Co ciekawe, możesz uzyskać dostęp do definicji, ale nic z niej nie wyodrębniasz; to znaczy zdefiniuj -DDEBUG = 5 (lub = "FOO"), a następnie spróbuj wydrukować to za pomocą "println (DEBUG to (DEBUG)". Ta linia nie generuje błędów, ale nic nie robi.
David H
10
Uwaga: „Ustawienia wbudowane -> Kompilator Swift -> Flagi niestandardowe” nie są widoczne w ustawieniach kompilacji „Podstawowe”. Aby była wyświetlana, musi zawierać ustawienia kompilacji „Wszystkie”.
Levibostian
7
@EugeneDubinin prawdopodobnie dlatego, że powinieneś upewnić się, że $(inherited)jest używany w ustawieniach docelowych do dziedziczenia ustawień projektu.
DanSkeel,
2
@DanSkeel niezły chwyt, dodanie $(inherited)sprawia , że mój komentarz jest nieistotny, dziękuję!
Yevhen Dubinin
10
W Xcode 8 jest teraz także ustawienie „Aktywne warunki kompilacji” w sekcji „Swift Compiler - Flagi niestandardowe”. Możesz dodać flagi tutaj bez konieczności użycia -D
Marcus
32

Napotkaliśmy problem polegający na tym, że nie chcieliśmy ustawiać flag szybkiego kompilatora, ponieważ nie chcieliśmy ich ustawiać i aktualizować dla różnych celów itp. Ponadto w naszej mieszanej bazie kodów nie chcieliśmy pamiętać ustawiać nasze flagi odpowiednio przez cały czas dla każdego języka.

W naszym zadeklarowaliśmy plik w ObjC

PreProcessorMacros.h

extern BOOL const DEBUG_BUILD;

W nich

PreProcessorMacros.m

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

Następnie w nagłówku pomostowym Objective-C

#import "PreProcessorMacros.h"

Teraz użyj tego w swojej bazie kodu Swift

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

Jest to zdecydowanie obejście, ale rozwiązało nasz problem, więc opublikowałem go tutaj w nadziei, że pomoże. Nie oznacza to, że istniejące odpowiedzi są nieważne.

Logan
źródło
11
Celem makr jest zmiana kodu w oparciu o konfigurację kompilacji. Przywracasz if z powrotem do środowiska wykonawczego, nie potrzebujesz do tego makr.
Berik
18
@Berik - zamieściłem poprawne rozwiązanie w nadziei, że może ono również pomóc innym próbującym rozwiązać pewien aspekt tego problemu, szczególnie w projektach wielojęzycznych. Jeśli twój problem wymaga nie kompilowania określonego kodu, to w porządku. Również komentarz jest w porządku, zwłaszcza gdy uświadamia niektórym, dlaczego może to nie być dla nich rozwiązaniem. Poproszę również o zanotowanie w odpowiedzi informacji o ograniczeniach tego podejścia. Głosowanie w dół jest niepotrzebne i zniechęca do alternatywnych rozwiązań, które mogą być pomocne dla innych osób rozwiązujących podobne problemy. Ponadto op mówi „Nie obchodzi mnie, czy kod został skompilowany”.
Logan
5

Szybsze rozwiązanie metody Logansa. Ustaw -D DEBUGw Other Swift Flagsod Swift Compiler - Custom Flagssekcji w ustawieniach kompilacji docelowego.

Następnie zadeklaruj następującą metodę w zakresie globalnym:

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

Teraz użyj go jako

if isDebugMode {
    // Do debug stuff
}
Sahil Kapoor
źródło
1

Dla mnie ustaw element debugowania „ Active Compilation Condition ” na „DEBUG” działał.

Następnie użycie klawisza DEBGU w #IF DEBUG działa w trybie debugowania, a #ELSE w trybie wydania:

  1. Wybierz swój cel,
  2. Na karcie Ustawienia kompilacji wyszukaj „Aktywny warunek kompilacji”,
  3. Ustaw wartość elementu „Debug” na „YourKeyWord”,
  4. Użyj po prostu w następujący sposób:

    #if DEBUG
        print("You'r running in DEBUG mode!")
    #else
        print("You'r running in RELEASE mode!")
    #endif
    
Marjan Basiri
źródło
0

Pracuję w bazie kodu języka mieszanego, w którym kod obj-c używa makra do wysyłania komunikatów debugowania do konsoli (a to makro zależy od naszej flagi preprocesora debugowania). Chciałem móc wywołać to samo makro w szybkim kodzie ...

  1. Utworzyłem metodę klasy na jednej z moich klas obj-c, która jest opakowaniem wokół tego makra.
  2. Dodałem ten nagłówek obj-c do naszego pliku nagłówkowego mostu.
  3. Teraz mój szybki kod wywołuje tę metodę klasy jako „proxy” dla makra obj-c.

To trochę denerwujące, że nie mogę po prostu wywołać makra bezpośrednio w szybkim kodzie, ale przynajmniej teraz mam tylko jedno miejsce w projekcie, aby martwić się włączaniem / wyłączaniem flagi debugowania.

ghostatron
źródło