Swift: як використовувати прапори PREPROCESSOR (наприклад, `#if DEBUG`) для реалізації ключів API?


95

У 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 більше не використовує препроцесор?

Відповіді:


161

Apple включила повну підтримку прапорців препроцесора Swift станом на Xcode 8 , тому більше не потрібно встановлювати ці значення в "Інші прапорці Swift".

Новий параметр називається "Умови активної компіляції", який забезпечує підтримку на найвищому рівні еквівалента Swift прапорців препроцесора. Ви використовуєте його точно так само, як і "Інші швидкі прапори", за винятком того, що немає необхідності додавати значення до "-D" (так це просто трохи чистіше).

З приміток до випуску Xcode 8 :

Active Compilation Conditions- це новий параметр збірки для передачі прапорів умовної компіляції компілятору Swift. Кожен елемент значення цього параметра переходить до swiftc з префіксом -D, так само, як елементи Preprocessor Macrosпереходу до clang з однаковим префіксом. (22457329)

введіть тут опис зображення

Ви використовуєте вищевказане налаштування так:

#if DEBUG
    let accessToken = "DebugAccessToken"
#else
    let accessToken = "ProductionAccessToken"
#endif

2
Примітка: ви не повинні вказувати = 1 або будь-яке інше = значення. Швидше, вам потрібно просто вказати назву прапора. :]
JRG-Developer,

@ JRG-Developer Я не погоджуюсь, але я не впевнений, як тут застосовується ваш коментар.
Dan Loewenherz,

9
Це корисна відповідь, але, виходячи з фону Objective-C (як я уявляю, багатьом розробникам iOS), я припустив, що мені потрібно вказати =1... Я втратив трохи часу, намагаючись зрозуміти, чому це не працює коли я це зробив. Отже, я думав поділитися цим тріском, щоб допомогти наступному хлопцеві. :] У будь-якому разі, дякую за вашу відповідь тут!
JRG-Developer,

1
@ JRG-Developer, @Dan Loewenherz Я встановив як DEBUGв, так Active Compilation Conditionsі DEBUG=1всередині, Preprocessor Macrosі ця конфігурація взагалі не працює. Чи слід видаляти DEBUG=1?? З наведених коментарів не зрозуміло.
Bhavin_m

2
@DanLoewenherz Ви абсолютно праві. Я встановив "DEBUG" для конфігурації архіву в моїх цільових налаштуваннях, тому кожен раз, коли він запускає оператор Debug і ніколи не запускає умови випуску. Будь-хто, хто стикається з проблемою, спочатку перевірте свою ціль Build Configuration. Перевірте цю відповідь stackoverflow.com/questions/9063100/… для отримання додаткової інформації.
Bhavin_m

131

ОНОВЛЕНО: Xcode 8 тепер підтримує це автоматично, див. Відповідь @ DanLoewenherz вище.

До Xcode 8 ви все ще могли використовувати макроси таким же чином:

#if DEBUG
let apiKey = "KEY_A"
#else
let apiKey = "KEY_B"
#endif

Однак, щоб їх підняв Swift, вам потрібно встановити "Інші прапорці Swift" у налаштуваннях збірки вашої цілі:

  • Відкрийте параметри побудови для своєї цілі
  • Шукати "інші швидкі прапори"
  • Додайте макроси, які ви хочете використовувати, перед ними -Dпрапор

введіть тут опис зображення


ти мене вразив! для мене Це не працювало без -Dпрефікса
номном

5

Для подальшого спостереження намагайтеся не зберігати ключі / секрети API у відкритому тексті у сховищі. Використовуйте систему управління секретами для завантаження ключів / секретів у змінні середовища користувача. В іншому випадку необхідний крок 1, якщо це прийнятно.

  1. Помістіть "секрети" у файл відкритого тексту вище у сховищі, що додається
  2. Створіть, ../set_keys.shщо містить список export API_KEY_A='<plaintext_key_aef94c5l6>'(використовуйте одну лапку, щоб запобігти оцінці)
  3. Додайте сценарій запуску сценарію, який може, source ../set_keys.shі перемістіть його у верхню частину порядку виконання
  4. У Налаштування збірки> Препроцесорні макроси додайте до необхідних параметрів, таких як API_KEY_A="$API_KEY_A"

Це фіксує змінну середовища у визначенні компілятора, яке згодом використовується у кожному виклику дзвінків для кожного вихідного файлу.

Приклад структури каталогів

[10:33:15] ~/code/memo yes? tree -L 2 .
.
├── Memo
│   ├── Memo
│   ├── Memo.xcodeproj
│   ├── Memo.xcworkspace
│   ├── Podfile
│   ├── Podfile.lock
│   └── Pods
└── keys

0

У швидких пакетах ви повинні робити це всередині 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.