在C/C++/Objective-C中,您可以使用编译器预处理器定义宏.此外,您可以使用编译器预处理器包含/排除代码的某些部分.
#ifdef DEBUG // Debug-only code #endif
Swift中有类似的解决方案吗?
ifdef
Xcode 8提出了一个重大的替换更改,即使用Active Compilation Conditions.
请参阅建筑和链接在Xcode中8注版.
新的构建设置
新设置: SWIFT_ACTIVE_COMPILATION_CONDITIONS
“Active Compilation Conditions” is a new build setting for passing conditional compilation flags to the Swift compiler.
以前,我们必须在OTHER_SWIFT_FLAGS下声明您的条件编译标志,记住在设置前加上"-D".例如,要使用MYFLAG值进行有条件的编译:
#if MYFLAG1 // stuff 1 #elseif MYFLAG2 // stuff 2 #else // stuff 3 #endif
要添加到设置的值 -DMYFLAG
现在我们只需要将值MYFLAG传递给新设置.是时候移动所有这些条件编译值了!
有关Xcode 8中的更多Swift Build Settings功能,请参阅以下链接:http: //www.miqu.me/blog/2016/07/31/xcode-8-new-build-settings-and-analyzer-improvements/
是的,你可以做到.
在Swift中,您仍然可以使用"#if /#else /#endif"预处理器宏(尽管更受限制),如Apple文档所述.这是一个例子:
#if DEBUG let a = 2 #else let a = 3 #endif
现在,您必须在其他位置设置"DEBUG"符号.将它设置在"Swift Compiler - Custom Flags"部分,"Other Swift Flags"行中.您可以使用-D DEBUG
条目添加DEBUG符号.
像往常一样,您可以在Debug或Release中设置不同的值.
我在实际代码中测试它并且它工作; 但它似乎并没有在游乐场中得到认可.
你可以在这里阅读我的原帖.
重要说明: -DDEBUG=1
不起作用.只有-D DEBUG
作品.似乎编译器忽略了具有特定值的标志.
从Swift 4.1开始,如果您只需要检查代码是使用调试版还是发布版构建,那么您可以使用内置函数:
_isDebugAssertConfiguration()
(当优化设置为时为true -Onone
)
(不适用于Swift 3+)_isReleaseAssertConfiguration()
(当优化设置为时为true -O
)
_isFastAssertConfiguration()
(当优化设置为时为true -Ounchecked
)
例如
func obtain() -> AbstractThing { if _isDebugAssertConfiguration() { return DecoratedThingWithDebugInformation(Thing()) } else { return Thing() } }
与预处理器宏相比,
✓您无需定义自定义-D DEBUG
标志即可使用它
〜它实际上是根据优化设置定义的,而不是Xcode构建配置
✗未记录,这意味着可以在任何更新中删除该函数(但它应该是AppStore安全的,因为优化器会将这些转换为常量)
这些曾经被删除,但带回公众缺乏@testable
属性,未来斯威夫特的命运不确定.
✗在if/else中使用将始终生成"永不执行"警告.
如Apple Docs中所述
Swift编译器不包含预处理器.相反,它利用编译时属性,构建配置和语言功能来实现相同的功能.因此,预处理程序指令不会在Swift中导入.
我通过使用自定义构建配置设法实现了我想要的目标:
转到您的项目/选择目标/构建设置/搜索自定义标志
对于您选择的目标,使用-D前缀(不带空格)为Debug和Release设置自定义标志
为您拥有的每个目标执行上述步骤
以下是检查目标的方法:
#if BANANA print("We have a banana") #elseif MELONA print("Melona") #else print("Kiwi") #endif
使用Swift 2.2测试
我对Xcode 8的两分钱:
a)使用-D
前缀的自定义标志工作正常,但......
b)使用更简单:
在Xcode 8中有一个新的部分:"Active Compilation Conditions",已有两行,用于调试和发布.
只需添加您的定义WITHOUT -D
.
XCODE 9及以上
#if DEVELOP // #elseif PRODCTN // #else // #endif
另一个也许更简单的解决方案仍然会产生一个布尔值,你可以#if
在整个代码库中传递给函数而不需要调整条件,就是将它定义DEBUG
为你的项目构建目标之一Active Compilation Conditions
并包含以下内容(我将其定义为全局常量):
#if DEBUG let isDebug = true #else let isDebug = false #endif
这个概念建立在kennytm的答案之上
与kennytm进行比较时的主要优点是,这不依赖于私有或未记录的方法.
在Swift 4中:
let isDebug: Bool = { var isDebug = false // function with a side effect and Bool return value that we can pass into assert() func set(debug: Bool) -> Bool { isDebug = debug return isDebug } // assert: // "Condition is only evaluated in playgrounds and -Onone builds." // so isDebug is never changed to true in Release builds assert(set(debug: true)) return isDebug }()
与预处理器宏和kennytm的答案相比,
✓您无需定义自定义-D DEBUG
标志即可使用它
〜它实际上是根据优化设置定义的,而不是Xcode构建配置
✓已记录,这意味着该功能将遵循正常的API发布/弃用模式.
✓在if/else中使用不会生成"永不执行"警告.
没有Swift预处理器.(一方面,任意代码替换会破坏类型和内存安全性.)
但是,Swift确实包含构建时配置选项,因此您可以有条件地包含某些平台的代码或构建样式,或者响应您使用-D
编译器args 定义的标志.但是,与C不同,代码的有条件编译部分必须在语法上完整.在使用Swift With Cocoa和Objective-C时,有一节介绍了这一点.
例如:
#if os(iOS) let color = UIColor.redColor() #else let color = NSColor.redColor() #endif
设置完成后DEBUG=1
您的GCC_PREPROCESSOR_DEFINITIONS
生成设置我更喜欢使用的功能,使这个调用:
func executeInProduction(_ block: () -> Void) { #if !DEBUG block() #endif }
然后在这个函数中包含我想在Debug构建中省略的任何块:
executeInProduction { Fabric.with([Crashlytics.self]) // Compiler checks this line even in Debug }
与以下方面相比的优势:
#if !DEBUG Fabric.with([Crashlytics.self]) // This is not checked, may not compile in non-Debug builds #endif
是编译器检查我的代码的语法,所以我确信它的语法是正确的和构建.
Moignans 在这里的回答很好。如果有帮助,这里还有另一条信息,
#if DEBUG let a = 2 #else let a = 3 #endif
您可以像下面那样否定宏,
#if !RELEASE let a = 2 #else let a = 3 #endif
在许多情况下,您并不需要条件编译 ; 你只需要可以打开和关闭的条件行为.为此,您可以使用环境变量.这具有巨大的优势,您实际上不必重新编译.
您可以在方案编辑器中设置环境变量,并轻松打开或关闭它:
您可以使用NSProcessInfo检索环境变量:
let dic = NSProcessInfo.processInfo().environment if dic["TRIPLE"] != nil { // ... do secret stuff here ... }
这是一个真实的例子.我的应用程序仅在设备上运行,因为它使用模拟器上不存在的音乐库.那么,如何在模拟器上为我不拥有的设备拍摄屏幕截图?没有这些屏幕截图,我无法提交到AppStore.
我需要假数据和不同的处理方式.我有两个环境变量:一个在打开时告诉应用程序在我的设备上运行时从真实数据生成虚假数据; 另一个,当打开时,在模拟器上运行时使用假数据(而不是丢失的音乐库).由于Scheme编辑器中的环境变量复选框,可以轻松打开/关闭每个特殊模式.奖金是我不能在我的App Store构建中意外使用它们,因为归档没有环境变量.
在Build settings/Swift编译器中使用Active Compilation Conditions设置- 自定义标志.
这是用于将条件编译标志传递给Swift编译器的新构建设置.
简单的附加标志是这样的:ALPHA
,BETA
等等.
然后用这样的编译条件检查它:
#if ALPHA // #elseif BETA // #else // #endif
提示:您也可以使用
#if !ALPHA
等
在使用Xcode版本9.4.1,Swift 4.1创建的Swift项目中
#if DEBUG #endif
默认情况下,因为在预处理器宏中,DEBUG = 1已由Xcode设置.
所以你可以使用#if DEBUG"开箱即用".
顺便说一下,如何使用条件编译块一般是在Apple的书Swift编程语言4.1(编译器控件语句一节)中编写的,以及如何编写编译标志以及Swift中C宏的对应部分是用另一本Apple的书"将Swift与Cocoa和Objective C一起使用"(在预处理程序指令一节中)
希望将来Apple会为他们的书写下更详细的内容和索引.