Swift: как использовать флаги PREPROCESSOR (например, `#if DEBUG`) для реализации ключей API?
В Objective-C
иногда было полезно использовать статические строковые константы для определения альтернативных ключей API (например, чтобы различать ключи RELEASE и DEBUG для пакетов аналитики, таких как MixPanel, Flurry или Crashlytics):
#if DEBUG
static NSString *const API_KEY = @"KEY_A";
#else
static NSString *const API_KEY = @"KEY_B";
#endif
а потом...
[Analytics startSession:API_KEY];
Как это переводится в Swift, поскольку компилятор Swift больше не использует препроцессор?
2 ответа
Apple включила полную поддержку флагов препроцессора Swift начиная с Xcode 8, поэтому больше нет необходимости устанавливать эти значения в "Другие флаги Swift".
Новый параметр называется "Условия активной компиляции", который обеспечивает поддержку верхнего уровня для эквивалента флагов препроцессора Swift. Вы используете его точно так же, как и "другие быстрые флаги", за исключением того, что нет необходимости добавлять значение "-D" (так что это немного чище).
Из примечаний к выпуску Xcode 8:
Active Compilation Conditions
это новый параметр сборки для передачи флагов условной компиляции компилятору Swift. Каждый элемент значения этого параметра передается в swiftc с префиксом-
D, так же, как элементыPreprocessor Macros
перейти к лязгу с тем же префиксом. (22457329)
Вы используете вышеуказанную настройку следующим образом:
#if DEBUG
let accessToken = "DebugAccessToken"
#else
let accessToken = "ProductionAccessToken"
#endif
ОБНОВЛЕНО: Xcode 8 теперь поддерживает это автоматически, см. Ответ @DanLoewenherz выше.
До Xcode 8 вы все еще могли использовать макросы таким же образом:
#if DEBUG
let apiKey = "KEY_A"
#else
let apiKey = "KEY_B"
#endif
Однако для того, чтобы они были подобраны Swift, вам нужно установить "Другие флаги Swift" в настройках сборки вашей цели:
- Откройте настройки сборки для вашей цели
- Искать "другие быстрые флаги"
- Добавьте макросы, которые вы хотите использовать, перед
-D
флаг
В быстрых пакетах это нужно делать внутри swiftSettings
аргумент .target
в вашем Package.swift
файл. Использоватьdefine
метод (документация Apple) или документация Swift
targets: [
.target(name: String,
dependencies: [Target.Dependency],
path: String?,
exclude: [String]?,
sources: [String]?,,
cSettings: [CSetting]?,
cxxSettings: [CXXSetting]?,
swiftSettings: [SwiftSetting]?,
linkerSettings: [LinkerSetting]?),
Мой выглядит так и работает!
swiftSettings: [
.define("VAPOR")
]
в моем коде я могу условно скомпилировать, используя это:
#if VAPOR
В качестве последующего наблюдения постарайтесь не хранить ключи / секреты API в открытом тексте в хранилище. Используйте систему управления секретами для загрузки ключей / секретов в переменные среды пользователя. В противном случае шаг 1 необходим, если он приемлем.
- Поместите "секреты" в текстовом файле выше в прилагаемом хранилище
- Создать
../set_keys.sh
который содержит списокexport API_KEY_A='<plaintext_key_aef94c5l6>'
(используйте одинарную кавычку для предотвращения оценки) - Добавьте этап сценария запуска, который может
source ../set_keys.sh
и переместить его в верхнюю часть порядка выполнения - В "Параметры сборки"> "Макросы препроцессора" добавьте в определения при необходимости, например:
API_KEY_A="$API_KEY_A"
Это захватывает переменную окружения в определение компилятора, которое позже используется в каждом вызове clang для каждого исходного файла.
Пример структуры каталогов
[10:33:15] ~/code/memo yes? tree -L 2 .
.
├── Memo
│ ├── Memo
│ ├── Memo.xcodeproj
│ ├── Memo.xcworkspace
│ ├── Podfile
│ ├── Podfile.lock
│ └── Pods
└── keys