117

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

4 回答 4

190

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

新设置称为“活动编译条件”,它为 Swift 等效的预处理器标志提供顶级支持。使用它的方式与使用“Other Swift Flags”完全相同,只是不需要在值前加上“-D”(所以它更简洁一些)。

来自Xcode 8 发行说明

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

在此处输入图像描述

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

#if DEBUG
    let accessToken = "DebugAccessToken"
#else
    let accessToken = "ProductionAccessToken"
#endif
于 2017-11-20T15:28:31.553 回答
134

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

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

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

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

  • 为您的目标打开构建设置
  • 搜索“其他快速标志”
  • 添加您希望使用的宏,前面带有-D标志

在此处输入图像描述

于 2016-08-07T11:58:39.523 回答
5

作为后续观察,尽量不要将 api 密钥/秘密以明文形式保存在存储库中。使用秘密管理系统将密钥/秘密加载到用户的环境变量中。否则,如果可以接受,则必须执行第 1 步。

  1. 将“秘密”放在上面封闭存储库中的纯文本文件中
  2. 创建一个../set_keys.sh包含列表的export API_KEY_A='<plaintext_key_aef94c5l6>'(使用单引号来防止评估)
  3. 添加一个可以运行的脚本阶段source ../set_keys.sh并将其移动到执行顺序的顶部
  4. 在 Build Settings > Preprocessor Macros 中,根据需要添加到定义,例如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
于 2019-08-01T05:34:14.630 回答
4

在 swift 包中,您必须在文件的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
于 2020-07-29T16:18:44.263 回答