В C / C ++ / Objective C вы можете определить макрос, используя препроцессоры компилятора. Кроме того, вы можете включать / исключать некоторые части кода, используя препроцессоры компилятора.
#ifdef DEBUG
// Debug-only code
#endif
Есть ли подобное решение в Swift?
Ответы:
Да, ты можешь сделать это.
В Swift вы все еще можете использовать макросы препроцессора "# if / # else / # endif" (хотя и более ограниченные), как указано в документации Apple . Вот пример:
Теперь вы должны установить символ «DEBUG» в другом месте. Установите его в разделе «Swift Compiler - Custom Flags», строка «Другие флаги Swift». Вы добавляете символ DEBUG вместе с
-D DEBUG
записью.Как обычно, вы можете установить другое значение в Debug или в Release.
Я проверил это в реальном коде, и он работает; это, кажется, не признается на детской площадке, хотя.
Вы можете прочитать мой оригинальный пост здесь .
ВАЖНОЕ ПРИМЕЧАНИЕ:
-DDEBUG=1
не работает. Только-D DEBUG
работает. Кажется, компилятор игнорирует флаг с определенным значением.источник
-D DEBUG
как указано выше, вам также нужно определитьDEBUG=1
вApple LLVM 6.0 - Preprocessing
->Preprocessor Macros
.-DDEBUG
с этого ответа: stackoverflow.com/a/24112024/747369 .DEBUG=1
кPreprocessor Macros
, если вы не хотите использовать его в коде Objective-C.Как указано в Apple Docs
Мне удалось достичь того, чего я хотел, используя пользовательские конфигурации сборки:
Вот как вы проверяете цель:
Протестировано с использованием Swift 2.2
источник
-DLOCAL
, на моем#if LOCAl #else #endif
, он попадает в#else
раздел. Я продублировал оригинальную цельAppTarget
и переименовал ее вAppTargetLocal
& установил ее собственный флаг.#if LOCAL
соответствует ожидаемому результату, когда я бегу с симулятором, и попадаю во#else
время тестирования. Я хочу, чтобы это также попало во#if LOCAL
время тестирования.Во многих ситуациях вам не нужна условная компиляция ; вам просто нужно условное поведение, которое вы можете включать и выключать. Для этого вы можете использовать переменную окружения. Это имеет огромное преимущество в том, что вам не нужно перекомпилировать.
Вы можете установить переменную окружения и легко включить или выключить ее в редакторе схем:
Вы можете получить переменную среды с NSProcessInfo:
Вот пример из жизни. Мое приложение работает только на устройстве, потому что оно использует музыкальную библиотеку, которой нет в симуляторе. Как же тогда делать снимки экрана на симуляторе для устройств, которыми я не владею? Без этих снимков экрана я не могу отправить в AppStore.
Мне нужны поддельные данные и другой способ их обработки . У меня есть две переменные окружения: одна, которая при включении говорит приложению генерировать поддельные данные из реальных данных во время работы на моем устройстве; другой, который при включении использует фальшивые данные (не отсутствующую музыкальную библиотеку) во время работы на симуляторе. Включить / отключить каждый из этих специальных режимов легко благодаря флажкам переменных среды в редакторе схем. И бонус в том, что я не могу случайно использовать их в моей сборке App Store, потому что архивация не имеет переменных среды.
источник
Главное изменение
ifdef
замены пришло с Xcode 8. то есть использование Активных Условий Компиляции .См. Построение и Связывание в Примечании к выпуску Xcode 8 .
Новые настройки сборки
Новая настройка:
SWIFT_ACTIVE_COMPILATION_CONDITIONS
Ранее нам приходилось объявлять флаги условной компиляции в OTHER_SWIFT_FLAGS, не забывая добавлять «-D» к настройке. Например, для условной компиляции со значением MYFLAG:
Значение, добавляемое к настройке
-DMYFLAG
Теперь нам нужно только передать значение MYFLAG в новую настройку. Время переместить все эти условные значения компиляции!
Пожалуйста, обратитесь к ссылке ниже для получения дополнительной функции Настройки сборки Swift в Xcode 8: http://www.miqu.me/blog/2016/07/31/xcode-8-new-build-settings-and-analyzer-improvements/
источник
Начиная с Swift 4.1, если все, что вам нужно, это просто проверить, собран ли код с конфигурацией отладки или выпуска, вы можете использовать встроенные функции:
_isDebugAssertConfiguration()
(верно, когда оптимизация установлена в-Onone
)(недоступно в Swift 3+)_isReleaseAssertConfiguration()
(верно, когда оптимизация установлена в-O
)_isFastAssertConfiguration()
(верно, когда оптимизация установлена в-Ounchecked
)например
По сравнению с макросами препроцессора,
-D DEBUG
флаг, чтобы использовать егоOcu Недокументированное, что означает, что функция может быть удалена при любом обновлении (но она должна быть безопасной для AppStore, так как оптимизатор превратит их в константы)
@testable
атрибутов , судьба которых неясна для будущего Swift.In Использование в if / else всегда будет генерировать предупреждение «никогда не будет выполнено».
источник
if _isDebugAssertConfiguration()
будет оцениватьсяif false
в режиме выпуска и в режимеif true
отладки.Xcode 8 и выше
Используйте параметр « Условия активной компиляции» в « Параметры сборки» / «Компилятор Swift» - пользовательские флаги .
ALPHA
иBETA
т. Д.Затем проверьте это с условиями компиляции, как это:
источник
Нет препроцессора Swift. (С одной стороны, произвольная замена кода нарушает безопасность типов и памяти.)
Swift действительно включает параметры конфигурации во время сборки, поэтому вы можете условно включать код для определенных платформ или стилей сборки или в ответ на флаги, которые вы определяете с помощью
-D
аргументов компилятора. В отличие от C, условно скомпилированный раздел вашего кода должен быть синтаксически завершен. Об этом есть раздел « Использование Swift с какао и Objective-C» .Например:
источник
INT_CONST
куда угодно afloat
. Свифт не допустит этого. Кроме того, если бы вы могли сделать этоvar floatVal = INT_CONST
неизбежно, это могло бы произойти сбой где-то позже, когда компилятор ожидает,Int
но вы используете его какFloat
(типfloatVal
будет выведен какInt
). 10 кастов спустя, и это просто чище, чтобы удалить макросы ...Мои два цента для Xcode 8:
а) Пользовательский флаг с использованием
-D
префикса работает нормально, но ...б) более простое использование:
В Xcode 8 есть новый раздел: «Условия активной компиляции», уже с двумя строками, для отладки и выпуска.
Просто добавьте свое определение БЕЗ
-D
.источник
-D
.Константа isDebug на основе условий активной компиляции
Другое, возможно, более простое, решение, которое все еще приводит к логическому значению, которое вы можете передавать в функции, не вставляя
#if
условные обозначения по всей вашей кодовой базе, - это определитьDEBUG
как одну из целей сборки вашего проектаActive Compilation Conditions
и включить следующее (я определяю это как глобальную константу):Константа isDebug на основе настроек оптимизации компилятора
Эта концепция основана на ответе Кеннимма
Основное преимущество по сравнению с Kennytm заключается в том, что это не зависит от частных или недокументированных методов.
В Swift 4 :
По сравнению с макросами препроцессора и ответом kennytm ,
-D DEBUG
флаг, чтобы использовать его✓ Документировано , что означает, что функция будет следовать нормальным шаблонам выпуска / устаревания API.
✓ Использование в if / else не будет генерировать предупреждение «никогда не будет выполнено».
источник
Ответ Moignans здесь отлично работает. Вот еще одна информация, если это поможет,
Вы можете отменить макросы, как показано ниже,
источник
В проектах Swift, созданных с версией Xcode 9.4.1, Swift 4.1
работает по умолчанию, потому что в макросах препроцессора DEBUG = 1 уже был установлен Xcode.
Так что вы можете использовать #if DEBUG "из коробки".
Между прочим, как использовать блоки компиляции условий в общем, написано в книге Apple «Язык программирования Swift 4.1» (раздел «Операции управления компилятором»), и как написать флаги компиляции и что является аналогом макросов C в Swift, написано в другая книга Apple, использующая Swift с какао и Objective C (в разделе Директивы препроцессора)
Надеюсь, что в будущем Apple напишет более подробное содержание и индексы для своих книг.
источник
XCODE 9 И ВЫШЕ
источник
После настройки
DEBUG=1
в настройкахGCC_PREPROCESSOR_DEFINITIONS
сборки я предпочитаю использовать функцию для выполнения этих вызовов:А затем просто включите в эту функцию любой блок, который я хочу опустить в сборках Debug:
Преимущество по сравнению с:
Это то, что компилятор проверяет синтаксис моего кода, поэтому я уверен, что его синтаксис правильный и строит.
источник
! [В Xcode 8 и выше перейдите к настройке сборки -> поиск пользовательских флагов] 1
В коде
источник
Источник
источник
@inlinable
перед,func
и это будет самый элегантный и идиоматический способ для Swift. В сборках релизов вашcode()
блок будет оптимизирован и полностью исключен. Аналогичная функция используется в собственной платформе NIO от Apple.Это основывается на ответе Джона Уиллиса , основанном на утверждении, которое выполняется только в отладочных компиляциях:
Мой вариант использования для регистрации операторов печати. Вот эталон для Релиз-версии на iPhone X:
печатает:
Похоже, Swift 4 полностью исключает вызов функции.
источник