W C / C ++ / Objective C możesz zdefiniować makro za pomocą preprocesorów kompilatora. Co więcej, możesz włączyć / wyłączyć niektóre części kodu za pomocą preprocesorów kompilatora.
#ifdef DEBUG
// Debug-only code
#endif
Czy istnieje podobne rozwiązanie w Swift?
Odpowiedzi:
Tak, możesz to zrobić.
W Swift nadal możesz używać makr preprocesora „# if / # else / # endif” (choć bardziej ograniczone), zgodnie z dokumentami Apple . Oto przykład:
Teraz jednak musisz ustawić symbol „DEBUG” w innym miejscu. Ustaw go w sekcji „Swift Compiler - Custom Flags”, w wierszu „Other Swift Flags”. Dodajesz symbol DEBUG z
-D DEBUG
wpisem.Jak zwykle, możesz ustawić inną wartość podczas debugowania lub wydania.
Przetestowałem to w prawdziwym kodzie i działa; wydaje się, że nie jest rozpoznawany na placu zabaw.
Możesz przeczytać mój oryginalny post tutaj .
WAŻNA UWAGA:
-DDEBUG=1
nie działa.-D DEBUG
Działa tylko . Wydaje się, że kompilator ignoruje flagę o określonej wartości.źródło
-D DEBUG
jak wspomniano powyżej, musisz także zdefiniowaćDEBUG=1
wApple LLVM 6.0 - Preprocessing
->Preprocessor Macros
.-DDEBUG
z tej odpowiedzi: stackoverflow.com/a/24112024/747369 .DEBUG=1
doPreprocessor Macros
, jeśli nie chcesz go używać w kodzie Objective-C.Jak stwierdzono w Apple Docs
Udało mi się osiągnąć to, co chciałem, używając niestandardowych konfiguracji kompilacji:
Oto jak sprawdzasz cel:
Testowane przy użyciu Swift 2.2
źródło
-DLOCAL
na mój#if LOCAl #else #endif
wpada do#else
sekcji. Zduplikowałem oryginalny celAppTarget
i zmieniłem jego nazwę naAppTargetLocal
i ustawiłem niestandardową flagę.#if LOCAL
zamierzony rezultat, kiedy uruchamiam z symulatorem i wpada#else
podczas testowania. Chcę, żeby do tego doszło#if LOCAL
również podczas testów.W wielu sytuacjach tak naprawdę nie potrzebujesz kompilacji warunkowej ; potrzebujesz tylko zachowania warunkowego , które możesz włączać i wyłączać. W tym celu możesz użyć zmiennej środowiskowej. Ma to tę ogromną zaletę, że tak naprawdę nie trzeba go ponownie kompilować.
Możesz ustawić zmienną środowiskową i łatwo ją włączyć lub wyłączyć w edytorze schematów:
Możesz pobrać zmienną środowiskową za pomocą NSProcessInfo:
Oto prawdziwy przykład. Moja aplikacja działa tylko na urządzeniu, ponieważ korzysta z biblioteki muzycznej, która nie istnieje w Symulatorze. Jak zatem robić zrzuty ekranu na symulatorze dla urządzeń, których nie posiadam? Bez tych zrzutów ekranu nie mogę przesłać do AppStore.
Potrzebuję fałszywych danych i innego sposobu ich przetwarzania . Mam dwie zmienne środowiskowe: jedna, która po włączeniu informuje aplikację, aby wygenerowała fałszywe dane z rzeczywistych danych podczas działania na moim urządzeniu; drugi, który po włączeniu korzysta z fałszywych danych (nie brakującej biblioteki muzycznej) podczas działania na symulatorze. Włączanie / wyłączanie każdego z tych trybów specjalnych jest łatwe dzięki polom wyboru zmiennych środowiskowych w edytorze schematów. Dodatkową zaletą jest to, że nie mogę przypadkowo użyć ich w mojej wersji App Store, ponieważ archiwizacja nie ma zmiennych środowiskowych.
źródło
Główną zmianą
ifdef
zastąpienia była Xcode 8. tj. Użycie Aktywnych warunków kompilacji .Zobacz Budowanie i łączenie w Uwagach Xcode 8 .
Nowe ustawienia kompilacji
Nowe ustawienie:
SWIFT_ACTIVE_COMPILATION_CONDITIONS
Wcześniej musieliśmy zadeklarować flagi warunkowej kompilacji w ramach opcji OTHER_SWIFT_FLAGS, pamiętając o dodaniu „-D” do ustawienia. Na przykład, aby warunkowo skompilować z wartością MYFLAG:
Wartość do dodania do ustawienia
-DMYFLAG
Teraz musimy tylko przekazać wartość MYFLAG do nowego ustawienia. Czas przenieść wszystkie te warunkowe wartości kompilacji!
Proszę zapoznać się z poniższym linkiem, aby uzyskać więcej funkcji Swift Build Settings w Xcode 8: http://www.miqu.me/blog/2016/07/31/xcode-8-new-build-settings-and-analyzer-improvements/
źródło
Począwszy od wersji Swift 4.1, jeśli wszystko, czego potrzebujesz, to po prostu sprawdź, czy kod jest zbudowany z konfiguracją debugowania lub wydania, możesz użyć wbudowanych funkcji:
_isDebugAssertConfiguration()
(prawda, gdy optymalizacja jest ustawiona na-Onone
)(niedostępne w Swift 3+)_isReleaseAssertConfiguration()
(prawda, gdy optymalizacja jest ustawiona na-O
)_isFastAssertConfiguration()
(prawda, gdy optymalizacja jest ustawiona na-Ounchecked
)na przykład
W porównaniu z makrami preprocesora,
-D DEBUG
flagi, aby z niej korzystać✗ Nieudokumentowane, co oznacza, że funkcję można usunąć w dowolnej aktualizacji (ale powinna być bezpieczna dla AppStore, ponieważ optymalizator zamieni je w stałe)
@testable
atrybutów , los niepewny w przyszłym Swift.✗ Używanie w, jeśli / else zawsze generuje ostrzeżenie „Nigdy nie zostanie wykonane”.
źródło
if _isDebugAssertConfiguration()
zostanie oceniony jakoif false
w trybie zwolnienia iif true
jest trybem debugowania.Xcode 8 i nowsze wersje
Użyj ustawienia Aktywna kompilacja w Ustawieniach kompilacji / Kompilatora Swift - Niestandardowe flagi .
ALPHA
,BETA
etc.Następnie sprawdź to z takimi warunkami kompilacji :
źródło
Nie ma preprocesora Swift. (Po pierwsze, dowolne podstawienie kodu narusza bezpieczeństwo typu i pamięci.)
Swift zawiera jednak opcje konfiguracji czasu kompilacji, więc można warunkowo dołączyć kod dla niektórych platform lub stylów kompilacji lub w odpowiedzi na flagi zdefiniowane za pomocą
-D
argumentów kompilatora. Jednak w odróżnieniu od C sekcja warunkowo skompilowana musi być kompletna pod względem składniowym. Jest o tym mowa w Używanie Swift z kakao i Objective-C .Na przykład:
źródło
INT_CONST
dowolnym miejscu,float
które zostanie zaakceptowane. Swift na to nie pozwoli. Ponadto, jeśli mógłbyś to zrobićvar floatVal = INT_CONST
nieuchronnie, załamałby się gdzieś później, gdy kompilator oczekuje,Int
ale używasz go jakoFloat
(typfloatVal
byłby wywnioskowany jakoInt
). 10 rzutów później i po prostu czystsze usuwanie makr ...Moje dwa centy za Xcode 8:
a) Niestandardowa flaga korzystająca z
-D
prefiksu działa dobrze, ale ...b) Prostsze użycie:
W Xcode 8 dostępna jest nowa sekcja: „Aktywne warunki kompilacji”, już z dwoma wierszami, do debugowania i wydania.
Po prostu dodaj swoją definicję BEZ
-D
.źródło
-D
. bez .Stała isDebug oparta na aktywnych warunkach kompilacji
Innym, być może prostszym rozwiązaniem, które wciąż daje wynik logiczny, który można przekazać do funkcji bez pieprzania
#if
warunków warunkowych w całej bazie kodu, jest zdefiniowanieDEBUG
jednego z celów kompilacji projektuActive Compilation Conditions
i uwzględnienie następujących (definiuję go jako stałą globalną):Stała isDebug oparta na ustawieniach optymalizacji kompilatora
Ta koncepcja opiera się na odpowiedzi KennyTM
Główną zaletą w porównaniu z kennyTM jest to, że nie opiera się to na prywatnych ani nieudokumentowanych metodach.
W Swift 4 :
W porównaniu z makrami preprocesora i odpowiedzią KennyTM ,
-D DEBUG
flagi, aby z niej korzystać✓ Udokumentowane , co oznacza, że funkcja będzie działać zgodnie z normalnymi wzorcami wydawania / wycofywania API.
✓ Zastosowanie w, jeśli / else nie wygeneruje ostrzeżenia „Nigdy nie zostanie wykonane”.
źródło
Moignans, odpowiedź tutaj działa dobrze. Oto kolejny spokój informacji na wypadek, gdyby to pomogło,
Możesz zanegować makra jak poniżej,
źródło
W projektach Swift utworzonych za pomocą Xcode w wersji 9.4.1, Swift 4.1
działa domyślnie, ponieważ w Makrach Preprocesora DEBUG = 1 został już ustawiony przez Xcode.
Możesz więc użyć #if DEBUG „po wyjęciu z pudełka”.
Nawiasem mówiąc, jak ogólnie korzystać z bloków kompilacji warunków, jest napisane w książce Apple'a Swift Programming Language 4.1 (sekcja Instrukcje sterujące kompilatora) i jak napisać flagi kompilacji i co jest odpowiednikiem makr C w Swift jest napisane w kolejna książka Apple'a Używanie Swift z kakao i celem C (w sekcji Dyrektywy preprocesora)
Mam nadzieję, że w przyszłości Apple napisze bardziej szczegółowe treści i indeksy swoich książek.
źródło
XCODE 9 I POWYŻEJ
źródło
Po ustawieniu
DEBUG=1
wGCC_PREPROCESSOR_DEFINITIONS
Ustawieniach kompilacji wolę używać funkcji do wykonywania tych wywołań:A następnie dołącz do tej funkcji dowolny blok, który chcę pominąć w kompilacjach Debugowania:
Zaleta w porównaniu do:
Czy kompilator sprawdza składnię mojego kodu, więc jestem pewien, że jego składnia jest poprawna i buduje.
źródło
! [W Xcode 8 i wyżej przejdź do ustawienia kompilacji -> wyszukaj niestandardowe flagi] 1
W kodzie
źródło
Źródło
źródło
@inlinable
przed,func
a byłby to najbardziej elegancki i idiomatyczny sposób dla Swift. W kompilacjach wersji twójcode()
blok zostanie zoptymalizowany i całkowicie wyeliminowany. Podobna funkcja jest używana we własnym środowisku NIO firmy Apple.Opiera się to na odpowiedzi Jona Willisa, która opiera się na aser, która jest wykonywana tylko w kompilacjach Debug:
Mój przypadek użycia dotyczy rejestrowania drukowanych wyciągów. Oto punkt odniesienia dla wersji Release na iPhone X:
drukuje:
Wygląda na to, że Swift 4 całkowicie eliminuje wywołanie funkcji.
źródło