В отсутствие макроса препроцессора, есть ли способ определить конкретные флаги конкретной схемы на уровне проекта в проекте XCode

174

Перед Swift я бы определил набор схем для альфа, бета и дистрибутивных сборок. Каждая из этих схем будет иметь набор макросов, которые были определены для управления определенным поведением на уровне проекта. Простейшим примером является макрос DEBUG = 1, который определен по умолчанию для всех проектов Xcode в схеме по умолчанию для сборки Run. Можно запросить #ifdef DEBUG ... и принять соответствующие решения в коде, даже компилируя ненужный код.

Кажется, что этот тип конфигурационного гейтинга не так прост, используя swift, так как макросы не поддерживаются. Может кто-нибудь предложить аналогичный подход, мне все равно, если код компилируется, как таковой. Я хотел бы использовать функции, основанные на схеме сборки.

banDedo
источник

Ответы:

468

В Swift вы все еще можете использовать макросы препроцессора "# if / # else / # endif" (хотя и более ограниченные), как указано в документации Apple . Вот пример:

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

Теперь вы должны установить символ «DEBUG» в другом месте. Установите его в разделе «Swift Compiler - Custom Flags», строка «Другие флаги Swift». Вы добавляете символ DEBUG вместе с -D DEBUGзаписью.

(Настройки сборки -> Swift Compiler - Пользовательские флаги) введите описание изображения здесь

Как обычно, вы можете установить другое значение в Debug или в Release.

Я проверил это в реальном коде; Кажется, это не узнается на детской площадке.

Жан Ле Муаньян
источник
5
Обратите внимание, что вы также можете использовать строки #elseif, чтобы добавить больше тестов. Интересно, что вы можете получить доступ к определению, но ничего не извлечь из него; то есть, определите -DDEBUG = 5 (или = "FOO"), а затем попытайтесь напечатать его с помощью "println (DEBUG is (DEBUG)". Эта строка не генерирует ошибок, но ничего не делает.
Дэвид Х,
10
Примечание: «Встроенные настройки -> Swift Compiler -> Пользовательские флаги» не отображаются в «Базовых» настройках сборки. Должны показать "Все" настройки сборки, чтобы он появился.
Левибостиан
7
@EugeneDubinin, вероятно, потому что вы должны убедиться, что $(inherited)он используется в целевых настройках для наследования настроек проекта.
DanSkeel
2
@DanSkeel хороший улов, добавление $(inherited)делает мой комментарий неактуальным, спасибо!
Евгений Дубинин
10
В Xcode 8 теперь есть также настройка «Условия активной компиляции» в разделе «Swift Compiler - Custom Flags». Вы можете добавить флаги сюда без необходимости -D
Маркус
32

У нас возникла проблема с нежеланием устанавливать флаги компилятора swift, потому что мы не хотели устанавливать их и обновлять их для различных целей и т. Д. Кроме того, в нашей смешанной кодовой базе мы не хотели помнить установить наши флаги надлежащим образом все время для каждого языка.

Для наших мы объявили файл в ObjC

PreProcessorMacros.h

extern BOOL const DEBUG_BUILD;

В них

PreProcessorMacros.m

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

Затем в вашем заголовке Objective-C

#import "PreProcessorMacros.h"

Теперь используйте это в своей кодовой базе Swift

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

Это определенно обходной путь, но он решил нашу проблему, поэтому я разместил его здесь в надежде, что это поможет. Это не означает, что существующие ответы являются недействительными.

логан
источник
11
Весь смысл макросов в том, чтобы изменить код в зависимости от конфигурации сборки. Вы возвращаете if в среду выполнения, для этого вам не нужны макросы.
Берик
18
@Berik - я опубликовал правильное решение в надежде, что оно может также помочь другим, пытающимся решить аспект этой проблемы, особенно в многоязычных проектах. Если ваша проблема не требует компиляции определенного кода, это нормально. Также замечателен комментарий, особенно когда он учит некоторых, почему это не может быть решением для них. Также просим сделать отметку в ответе об ограничениях этого подхода. Понижающее голосование является ненужным и препятствует альтернативным решениям, которые могут быть полезны для других, решающих подобные проблемы. Кроме того, оп говорит: «Мне все равно, если код скомпилирован».
Логан
5

Более быстрое решение для метода Логана. Установить -D DEBUGв Other Swift Flagsиз Swift Compiler - Custom Flagsраздела в настройках сборки вашей цели.

Затем объявите следующий метод в глобальной области видимости:

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

Теперь используйте его как

if isDebugMode {
    // Do debug stuff
}
Сахил Капур
источник
1

Для меня, установить отладочный элемент « Active Compilation Condition » в «DEBUG» сработало.

Затем с помощью ключа DEBGU работа в #IF DEBUG работает в режиме отладки и #ELSE в режиме выпуска:

  1. Выберите вашу цель,
  2. На вкладке «Настройка сборки» найдите «Условие активной компиляции»,
  3. Установите значение его элемента «Debug» равным «YourKeyWord»,
  4. Используйте просто как следовать:

    #if DEBUG
        print("You'r running in DEBUG mode!")
    #else
        print("You'r running in RELEASE mode!")
    #endif
Марьян Басири
источник
0

Я работаю в смешанной языковой кодовой базе, где код obj-c использует макрос для отправки отладочных сообщений на консоль (и этот макрос опирается на наш флаг препроцессора отладки). Я хотел иметь возможность вызывать этот же макрос в быстром коде ...

  1. Я создал метод класса для одного из моих классов obj-c, который является оболочкой для этого макроса.
  2. Я добавил этот заголовок obj-c в наш заголовочный файл моста.
  3. Теперь мой быстрый код вызывает этот метод класса как «прокси» для макроса obj-c.

Немного раздражает, что я не могу просто вызвать макрос прямо в быстром коде, но, по крайней мере, теперь у меня есть только одно место в проекте, чтобы беспокоиться о включении / выключении моего флага отладки.

ghostatron
источник