Swift:如何使用PREPROCESSOR Flags(如`#if DEBUG`)来实现API密钥?

时间:2016-08-07 11:58:40

标签: swift xcode macros preprocessor

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编译器不再使用预处理器?

4 个答案:

答案 0 :(得分:115)

更新:Xcode 8现在自动支持,请参阅@ DanLoewenherz上面的回复。

在Xcode 8之前,您仍然可以以相同的方式使用宏:

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

但是为了让它们被Swift选中,你需要在目标的Build Settings中设置“Other Swift Flags”:

  • 打开目标的构建设置
  • 搜索“其他swift标志”
  • 添加您要使用的宏,前面有-D标志

enter image description here

答案 1 :(得分:97)

Apple从Xcode 8开始全面支持Swift预处理程序标志,因此不再需要在“其他Swift标志”中设置这些值。

新设置称为“活动编译条件”,它为Swift等效的预处理程序标志提供顶级支持。你以与“其他Swift标志”完全相同的方式使用它,除了不需要在“-D”之前添加值(所以它只是更清洁一点)。

来自Xcode 8 release notes

  

Active Compilation Conditions是一个新的构建设置,用于将条件编译标志传递给Swift编译器。此设置的值的每个元素都传递给前缀为- D的swiftc,就像Preprocessor Macros的元素传递给具有相同前缀的clang一样。 (22457329)

enter image description here

您可以像这样使用上述设置:

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

答案 2 :(得分:1)

作为后续观察,请尽量不要在存储库中以纯文本形式保留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"

这会将环境变量捕获到编译器定义中,以后将在每个源文件的每次clang调用中使用该变量。

示例目录结构

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

答案 3 :(得分:0)

在快速包中,您必须在swiftSettings文件中.target的{​​{1}}参数内执行此操作。使用Package.swift方法(Apple documentation)Swift documentation

define

我的看起来像这样并且可以正常工作!

targets: [
.target(name: String,
            dependencies: [Target.Dependency],
            path: String?,
            exclude: [String]?,
            sources: [String]?,,
            cSettings: [CSetting]?,
            cxxSettings: [CXXSetting]?,
            swiftSettings: [SwiftSetting]?,
            linkerSettings: [LinkerSetting]?),

在我的代码中,我可以使用以下条件进行编译:

            swiftSettings: [
               .define("VAPOR")
            ]