当前位置:   article > 正文

Swift语言中的#ifdef替换_swift #ifdef

swift #ifdef

本文翻译自:#ifdef replacement in the Swift language

In C/C++/Objective-C you can define a macro using compiler preprocessors. 在C / C ++ / Objective-C中,您可以使用编译器预处理程序定义宏。 Moreover, you can include/exclude some parts of code using compiler preprocessors. 此外,您可以使用编译器预处理程序包含/排除部分代码。

  1. #ifdef DEBUG
  2. // Debug-only code
  3. #endif

Is there a similar solution in Swift? Swift中有类似的解决方案吗?


#1楼

参考:https://stackoom.com/question/1ciLr/Swift语言中的-ifdef替换


#2楼

There is no Swift preprocessor. 没有Swift预处理器。 (For one thing, arbitrary code substitution breaks type- and memory-safety.) (一方面,任意代码替换都会破坏类型和内存安全性。)

Swift does include build-time configuration options, though, so you can conditionally include code for certain platforms or build styles or in response to flags you define with -D compiler args. 但是,Swift确实包含了构建时配置选项,因此您可以有条件地包含某些平台或构建样式的代码,或者响应使用-D编译器args定义的标志。 Unlike with C, though, a conditionally compiled section of your code must be syntactically complete. 但是,与C语言不同,代码的条件编译部分必须在语法上完整。 There's a section about this in Using Swift With Cocoa and Objective-C . Swift与Cocoa和Objective-C结合使用中有关于这一部分的内容。

For example: 例如:

  1. #if os(iOS)
  2. let color = UIColor.redColor()
  3. #else
  4. let color = NSColor.redColor()
  5. #endif

#3楼

Yes you can do it. 是的,你可以做到。

In Swift you can still use the "#if/#else/#endif" preprocessor macros (although more constrained), as per Apple docs . 在Swift中,按照Apple docs的规定 ,您仍然可以使用“#if /#else /#endif”预处理器宏(尽管有更多限制)。 Here's an example: 这是一个例子:

  1. #if DEBUG
  2. let a = 2
  3. #else
  4. let a = 3
  5. #endif

Now, you must set the "DEBUG" symbol elsewhere, though. 现在,您必须在其他位置设置“ DEBUG”符号。 Set it in the "Swift Compiler - Custom Flags" section, "Other Swift Flags" line. 在“ Swift编译器-自定义标志”部分的“其他Swift标志”行中进行设置。 You add the DEBUG symbol with the -D DEBUG entry. 您将DEBUG符号与-D DEBUG条目一起添加。

As usual, you can set a different value when in Debug or when in Release. 与往常一样,您可以在Debug或Release中设置不同的值。

I tested it in real code and it works; 我用真实代码对其进行了测试,并且可以正常工作。 it doesn't seem to be recognized in a playground though. 它似乎在操场上似乎未被认可。

You can read my original post here . 您可以在这里阅读我的原始帖子。


IMPORTANT NOTE: -DDEBUG=1 doesn't work. 重要说明: -DDEBUG=1不起作用。 Only -D DEBUG works. -D DEBUG有效。 Seems compiler is ignoring a flag with a specific value. 似乎编译器正在忽略具有特定值的标志。


#4楼

In many situations, you don't really need conditional compilation ; 在很多情况下,您实际上并不需要条件编译 you just need conditional behavior that you can switch on and off. 您只需要可以打开和关闭的条件行为即可。 For that, you can use an environment variable. 为此,您可以使用环境变量。 This has the huge advantage that you don't actually have to recompile. 这具有巨大的优势,您实际上不必重新编译。

You can set the environment variable, and easily switch it on or off, in the scheme editor: 您可以在方案编辑器中设置环境变量,并轻松地将其打开或关闭:

在此处输入图片说明

You can retrieve the environment variable with NSProcessInfo: 您可以使用NSProcessInfo检索环境变量:

  1. let dic = NSProcessInfo.processInfo().environment
  2. if dic["TRIPLE"] != nil {
  3. // ... do secret stuff here ...
  4. }

Here's a real-life example. 这是一个真实的例子。 My app runs only on the device, because it uses the music library, which doesn't exist on the Simulator. 我的应用程序仅在设备上运行,因为它使用的音乐库在模拟器上不存在。 How, then, to take screen shots on the Simulator for devices I don't own? 那么,如何在模拟器上为我不拥有的设备拍摄屏幕截图? Without those screen shots, I can't submit to the AppStore. 没有这些屏幕截图,我将无法提交到AppStore。

I need fake data and a different way of processing it . 我需要伪造数据其他处理方式 I have two environment variables: one which, when switched on, tells the app to generate the fake data from the real data while running on my device; 我有两个环境变量:一个在打开时告诉应用程序在设备上运行时从真实数据生成假数据; the other which, when switched on, uses the fake data (not the missing music library) while running on the Simulator. 另一种是在模拟器上运行时打开时使用伪造的数据(而不是缺少的音乐库)。 Switching each of those special modes on / off is easy thanks to environment variable checkboxes in the Scheme editor. 通过使用方案编辑器中的环境变量复选框,可以轻松打开/关闭这些特殊模式。 And the bonus is that I can't accidentally use them in my App Store build, because archiving has no environment variables. 而且好处是,我不会在App Store构建中意外使用它们,因为归档没有环境变量。


#5楼

As of Swift 4.1, if all you need is just check whether the code is built with debug or release configuration, you may use the built-in functions: 从Swift 4.1开始,如果只需要检查代码是使用调试还是发布配置构建的,则可以使用内置函数:

  • _isDebugAssertConfiguration() (true when optimization is set to -Onone ) _isDebugAssertConfiguration() (当优化设置为-Onone时为-Onone
  • _isReleaseAssertConfiguration() (true when optimization is set to -O ) _isReleaseAssertConfiguration() (将优化设置为-O时为true) (not available on Swift 3+) (不适用于Swift 3+)
  • _isFastAssertConfiguration() (true when optimization is set to -Ounchecked ) _isFastAssertConfiguration() (当优化设置为-Ounchecked时为-Ounchecked

eg 例如

  1. func obtain() -> AbstractThing {
  2. if _isDebugAssertConfiguration() {
  3. return DecoratedThingWithDebugInformation(Thing())
  4. } else {
  5. return Thing()
  6. }
  7. }

Compared with preprocessor macros, 与预处理器宏相比,

  • ✓ You don't need to define a custom -D DEBUG flag to use it ✓您无需定义自定义-D DEBUG标志即可使用它
  • ~ It is actually defined in terms of optimization settings, not Xcode build configuration 〜实际上是根据优化设置而不是Xcode构建配置定义的
  • ✗ Undocumented, which means the function can be removed in any update (but it should be AppStore-safe since the optimizer will turn these into constants) ✗未记录,这意味着该功能可以在任何更新中删除(但它应该是AppStore安全的,因为优化程序会将其转换为常量)

  • ✗ Using in if/else will always generate a "Will never be executed" warning. in在in / if / else中使用将始终生成“将永远不会执行”警告。


#6楼

As stated in Apple Docs Apple Docs中所述

The Swift compiler does not include a preprocessor. Swift编译器不包含预处理器。 Instead, it takes advantage of compile-time attributes, build configurations, and language features to accomplish the same functionality. 相反,它利用编译时属性,构建配置和语言功能来实现相同的功能。 For this reason, preprocessor directives are not imported in Swift. 因此,预处理器指令不会导入Swift中。

I've managed to achieve what I wanted by using custom Build Configurations: 通过使用自定义构建配置,我设法实现了想要的目标:

  1. Go to your project / select your target / Build Settings / search for Custom Flags 转到项目/选择目标/构建设置/搜索自定义标志
  2. For your chosen target set your custom flag using -D prefix (without white spaces), for both Debug and Release 对于所选目标,使用-D前缀(不带空格)设置调试和发布的自定义标志
  3. Do above steps for every target you have 对您拥有的每个目标执行上述步骤

Here's how you check for target: 检查目标的方法如下:

  1. #if BANANA
  2. print("We have a banana")
  3. #elseif MELONA
  4. print("Melona")
  5. #else
  6. print("Kiwi")
  7. #endif

在此处输入图片说明

Tested using Swift 2.2 使用Swift 2.2测试

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/223914
推荐阅读
相关标签
  

闽ICP备14008679号