Swift:如何使用PREPROCESSOR标志(例如#if DEBUG)来实现API密钥?


95

Objective-C某些情况下,使用静态字符串常量来定义备用API密钥(例如,区分分析包(例如MixPanel,Flurry或Crashlytics)的RELEASE和DEBUG密钥有时很有用):

#if DEBUG
static NSString *const API_KEY = @"KEY_A";
#else
static NSString *const API_KEY = @"KEY_B";
#endif

然后...

[Analytics startSession:API_KEY];

由于Swift编译器不再使用预处理器,这如何转换为Swift?

Answers:


161

Xcode 8开始,Apple包括对Swift预处理器标志的完全支持,因此不再需要在“其他Swift标志”中设置这些值。

新设置称为“活动编译条件”,它为Swift等效的预处理器标志提供顶级支持。使用它的方式与使用“其他Swift标志”的方式完全相同,除了不需要在值前加上“ -D”(这样会使它稍微清洁一点)。

Xcode 8发行说明

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

在此处输入图片说明

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

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

2
注意:您应该指定= 1或任何其他=价值。相反,您只需要指定标志名称即可。:]
JRG开发人员

@ JRG-Developer我不同意,但是我不确定您的评论在这里如何应用。
Dan Loewenherz

9
这是一个有用的答案,但是来自Objective-C背景(就像我想象的许多iOS开发人员一样),我认为我需要指定=1...我花了一些时间试图弄清楚为什么它不起作用当我这样做。所以,我想我会分享这个秘诀来帮助下一位。:]无论如何,谢谢您的回答!
JRG开发人员

1
@ JRG-Developer,@ Dan Loewenherz我已经设置了DEBUGinActive Compilation ConditionsDEBUG=1in,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拾取,您需要在目标的Build Settings中设置“ Other Swift Flags”:

  • 打开目标的构建设置
  • 搜索“其他迅速标记”
  • 添加您要使用的宏,并在-D标志之前

在此处输入图片说明


你让我今天一整天都感觉很好!对我来说,没有-D前缀就无法正常工作
nomnom

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"

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

示例目录结构

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

0

在快速包中,您必须在文件中的swiftSettings参数内部执行此操作。使用方法(Apple文档)Swift文档.targetPackage.swiftdefine

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.