[英]Swift: how to use PREPROCESSOR Flags (like `#if DEBUG`) to implement API keys?
In Objective-C
it was sometimes useful to use static string constants to define alternate API keys (for example to differentiate between RELEASE and DEBUG keys for analytics packages, like MixPanel, Flurry or Crashlytics):在
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
and then...接着...
[Analytics startSession:API_KEY];
How does this translate to Swift, since the Swift compiler no longer uses a preprocessor?这如何转化为 Swift,因为 Swift 编译器不再使用预处理器?
Apple included full support for Swift preprocessor flags as of Xcode 8 , so it's no longer necessary to set these values in "Other Swift Flags". Apple 从Xcode 8开始全面支持 Swift 预处理器标志,因此不再需要在“Other Swift Flags”中设置这些值。
The new setting is called "Active Compilation Conditions", which provides top-level support for the Swift equivalent of preprocessor flags.新设置称为“活动编译条件”,它为 Swift 等效的预处理器标志提供顶级支持。 You use it in exactly the same way as you would "Other Swift Flags", except there's no need to prepend the value with a "-D" (so it's just a little cleaner).
使用它的方式与使用“Other Swift Flags”完全相同,只是不需要在值前加上“-D”(所以它更简洁一些)。
From the Xcode 8 release notes :来自Xcode 8 发行说明:
Active Compilation Conditions
is a new build setting for passing conditional compilation flags to the Swift compiler.Active Compilation Conditions
是一种新的构建设置,用于将条件编译标志传递给 Swift 编译器。 Each element of the value of this setting passes to swiftc prefixed with-D
, in the same way that elements ofPreprocessor Macros
pass to clang with the same prefix.此设置值的每个元素都以
-D
为前缀传递给 swiftc,就像Preprocessor Macros
的元素以相同的前缀传递给 clang。 (22457329)(22457329)
You use the above setting like so:您可以像这样使用上述设置:
#if DEBUG
let accessToken = "DebugAccessToken"
#else
let accessToken = "ProductionAccessToken"
#endif
UPDATED: Xcode 8 now supports this automatically, see @dwlz's response above.更新:Xcode 8 现在自动支持此功能,请参阅上面@dwlz 的回复。
Prior to Xcode 8, you could still use Macros in the same way:在 Xcode 8 之前,您仍然可以以相同的方式使用宏:
#if DEBUG
let apiKey = "KEY_A"
#else
let apiKey = "KEY_B"
#endif
However in order for them to be picked up by Swift, you need to set "Other Swift Flags" in your target's Build Settings:但是,为了让 Swift 获取它们,您需要在目标的 Build Settings 中设置“Other Swift Flags”:
-D
flag-D
标志As a follow up observation, try not to keep api keys / secrets in plaintext in the repository.作为后续观察,尽量不要将 api 密钥/秘密以明文形式保存在存储库中。 Use a secrets management system to load the keys / secrets into the user's environment variables.
使用秘密管理系统将密钥/秘密加载到用户的环境变量中。 Otherwise step 1 is necessary, if acceptable.
否则,如果可以接受,则必须执行第 1 步。
../set_keys.sh
that contains a list of export API_KEY_A='<plaintext_key_aef94c5l6>'
(use single quote to prevent evaluation)../set_keys.sh
export API_KEY_A='<plaintext_key_aef94c5l6>'
列表的 ../set_keys.sh (使用单引号来防止评估)source ../set_keys.sh
and move it to the top of execution ordersource ../set_keys.sh
并将其移动到执行顺序的顶部API_KEY_A="$API_KEY_A"
API_KEY_A="$API_KEY_A"
That captures the environment variable into the compiler define which is later used in each clang invocation for each source file.这会将环境变量捕获到编译器定义中,稍后在每个源文件的每个 clang 调用中使用该环境变量。
Example directory structure示例目录结构
[10:33:15] ~/code/memo yes? tree -L 2 .
.
├── Memo
│ ├── Memo
│ ├── Memo.xcodeproj
│ ├── Memo.xcworkspace
│ ├── Podfile
│ ├── Podfile.lock
│ └── Pods
└── keys
In swift packages you have to do this inside of the swiftSettings
argument to .target
in your Package.swift
file.在 swift 包中,您必须在
Package.swift
文件中的.target
的swiftSettings
参数中执行此操作。 Use the define
method (Apple documentation) or Swift documentation使用
define
方法(Apple 文档)或Swift 文档
targets: [
.target(name: String,
dependencies: [Target.Dependency],
path: String?,
exclude: [String]?,
sources: [String]?,,
cSettings: [CSetting]?,
cxxSettings: [CXXSetting]?,
swiftSettings: [SwiftSetting]?,
linkerSettings: [LinkerSetting]?),
Mine looks like this and it works!我的看起来像这样,它的工作原理!
swiftSettings: [
.define("VAPOR")
]
in my code I can conditionally compile using this:在我的代码中,我可以有条件地使用它进行编译:
#if VAPOR
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.