#ifdef替换为Swift语言
在C/C++/Objective C中,可以使用编译器预处理器定义宏。 此外,可以使用编译器预处理器包含/排除部分代码#ifdef替换为Swift语言,swift,xcode,preprocessor,preprocessor-directive,Swift,Xcode,Preprocessor,Preprocessor Directive,在C/C++/Objective C中,可以使用编译器预处理器定义宏。 此外,可以使用编译器预处理器包含/排除部分代码 #ifdef DEBUG // Debug-only code #endif Swift中是否有类似的解决方案?没有Swift预处理器。(一方面,任意代码替换会破坏类型和内存安全。) 不过,Swift确实包含构建时配置选项,因此您可以有条件地包含特定平台或构建样式的代码,或者响应您使用-D编译器参数定义的标志。不过,与C不同的是,代码中有条件编译的部分必须是语法完整的
#ifdef DEBUG
// Debug-only code
#endif
Swift中是否有类似的解决方案?没有Swift预处理器。(一方面,任意代码替换会破坏类型和内存安全。) 不过,Swift确实包含构建时配置选项,因此您可以有条件地包含特定平台或构建样式的代码,或者响应您使用
-D
编译器参数定义的标志。不过,与C不同的是,代码中有条件编译的部分必须是语法完整的。这本书有一节是关于这个的
例如:
#if os(iOS)
let color = UIColor.redColor()
#else
let color = NSColor.redColor()
#endif
是的,你能做到
在Swift中,您仍然可以使用“#if/#else/#endif”预处理器宏(尽管受约束更多),如所示。下面是一个例子:
#if DEBUG
let a = 2
#else
let a = 3
#endif
现在,您必须在别处设置“DEBUG”符号。在“Swift编译器-自定义标志”部分的“其他Swift标志”行中进行设置。使用-D DEBUG
条目添加调试符号
通常,您可以在调试或发布时设置不同的值
我在真实的代码中测试了它,它可以工作;不过,在操场上,人们似乎认不出它
你可以读我原来的帖子
重要提示:
-DDEBUG=1
不起作用。只有-D调试
起作用。编译器似乎忽略了具有特定值的标志。在许多情况下,您并不真正需要条件编译;您只需要可以打开和关闭的条件行为。为此,可以使用环境变量。这有一个巨大的优势,您实际上不必重新编译
您可以在方案编辑器中设置环境变量,并轻松地将其打开或关闭:
您可以使用NSProcessInfo检索环境变量:
let dic = NSProcessInfo.processInfo().environment
if dic["TRIPLE"] != nil {
// ... do secret stuff here ...
}
这里有一个真实的例子。我的应用程序只在设备上运行,因为它使用的是模拟器上不存在的音乐库。那么,如何在模拟器上为我没有的设备拍摄屏幕快照呢?没有这些屏幕截图,我无法提交到AppStore
我需要假数据和不同的处理方式。我有两个环境变量:一个是打开时,告诉应用程序在我的设备上运行时从真实数据生成假数据;另一个,当打开时,在模拟器上运行时使用假数据(而不是丢失的音乐库)。由于“方案编辑器”(Scheme editor)中的“环境变量”(environment variable)复选框,可以轻松地打开/关闭这些特殊模式。另外,我不能在我的应用商店构建中意外使用它们,因为归档没有环境变量 从Swift 4.1开始,如果您只需要检查代码是使用调试配置还是发布配置生成的,您可以使用内置功能:
(当优化设置为\u isDebugAssertConfiguration()
时为true)-Onone
(当优化设置为\u isReleaseAssertConfiguration()
时为真)(在Swift 3+上不可用)-O
(当优化设置为\u isFastAssertConfiguration()
)-选中时为true
- ✓ 使用它不需要定义自定义的
标志-D DEBUG
- ~它实际上是根据优化设置定义的,而不是Xcode构建配置
- ✗ 未记录,这意味着该函数可以在任何更新中删除(但它应该是AppStore安全的,因为优化器会将其转换为常量)
- 这些曾经,但是,未来命运未卜
- ✗ 在if/else中使用将始终生成“永远不会执行”警告
#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中有一个新的部分:“活动编译条件”,
已包含两行,用于调试和发布
只需添加您的define而不使用
-D
Xcode 8对ifdef
进行了重大更改。i、 e使用活动编译条件
请参阅中的构建和链接
新生成设置
新设置:SWIFT\u活动\u编译\u条件
“Active Compilation Conditions” is a new build setting for passing conditional compilation flags to the Swift compiler.
以前,我们必须在其他_SWIFT_标志下声明您的条件编译标志,记住在设置前加“-D”。例如,要使用MYFLAG值有条件地编译:
#if MYFLAG1
// stuff 1
#elseif MYFLAG2
// stuff 2
#else
// stuff 3
#endif
要添加到设置中的值-DMYFLAG
现在我们只需要将值MYFLAG传递给新设置。是时候移动所有这些条件编译值了
有关Xcode 8中更快速的构建设置功能,请参阅以下链接:
Xcode 8及以上
使用生成设置/Swift编译器-自定义标志中的活动编译条件设置
- 这是用于将条件编译标志传递给Swift编译器的新生成设置
- 简单地添加如下标志:
,ALPHA
等BETA
#if MYFLAG1 // stuff 1 #elseif MYFLAG2 // stuff 2 #else // stuff 3 #endif
#if ALPHA // #elseif BETA // #else // #endif
#if DEBUG let isDebug = true #else let isDebug = false #endif
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 }()
func Log(_ str: String) { assert(DebugLog(str)) } func DebugLog(_ str: String) -> Bool { print(str) return true }
let iterations = 100_000_000 let time1 = CFAbsoluteTimeGetCurrent() for i in 0 ..< iterations { Log ("⧉ unarchiveArray:\(fileName) memoryTime:\(memoryTime) count:\(array.count)") } var time2 = CFAbsoluteTimeGetCurrent() print ("Log: \(time2-time1)" )
Log: 0.0
func executeInProduction(_ block: () -> Void) { #if !DEBUG block() #endif }
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
#if Live print("Live") #else print("debug") #endif
#if DEBUG #endif
#if DEVELOP // #elseif PRODCTN // #else // #endif
func inDebugBuilds(_ code: () -> Void) { assert({ code(); return true }()) }
#if DEBUG let a = 2 #else let a = 3 #endif
#if !RELEASE let a = 2 #else let a = 3 #endif
#if os(macOS) /* Checks the target operating system */ #if canImport(UIKit) /* Check if a module presents */ #if swift(<5) /* Check the Swift version */ #if targetEnvironment(simulator) /* Check envrionments like Simulator or Catalyst */ #if compiler(<7) /* Check compiler version */
#if DEBUG print("Debug mode") #endif