在没有预处理器宏的情况下,有没有办法在 Xcode 项目的项目级别定义实用的方案特定标志

Posted

技术标签:

【中文标题】在没有预处理器宏的情况下,有没有办法在 Xcode 项目的项目级别定义实用的方案特定标志【英文标题】:In absence of preprocessor macros, is there a way to define practical scheme specific flags at project level in Xcode project 【发布时间】:2014-07-29 11:54:23 【问题描述】:

在 swift 之前,我将为 alpha、beta 和分发构建定义一组方案。这些方案中的每一个都将具有一组宏,这些宏被定义为在项目级别控制某些行为。最简单的例子是 DEBUG=1 宏,它是默认为 Run 构建的默认方案中的所有 Xcode 项目定义的。可以查询#ifdef DEBUG ...并在代码中做出相应的决定,甚至编译出不必要的代码。

似乎这种类型的配置门控使用 swift 并不容易,因为不支持宏。有人可以提出一种类似的方法吗,我不在乎代码本身是否被编译出来。不过,我想根据构建方案对功能进行门控。

【问题讨论】:

【参考方案1】:

在 Swift 中,您仍然可以使用“#if/#else/#endif”预处理器宏(尽管受到更多限制),如 Apple docs。这是一个例子:

#if DEBUG
    let a = 2
#else
    let a = 3
#endif

现在,您必须在别处设置“DEBUG”符号。在“Swift Compiler - Custom Flags”部分的“Other Swift Flags”行中设置它。使用 -D DEBUG 条目添加 DEBUG 符号。

(构建设置 -> Swift 编译器 - 自定义标志)

像往常一样,您可以在调试或发布时设置不同的值。

我用真实代码测试过它;在操场上似乎无法识别它。

【讨论】:

请注意,您还可以使用#elseif 行添加更多测试。有趣的是,您可以访问定义但不从中提取任何内容;也就是说,定义 -DDEBUG=5(或 ="FOO"),然后尝试使用“println(DEBUG is (DEBUG)”打印它。该行不会产生错误,但不会执行任何操作。 注意:“内置设置 -> Swift 编译器 -> 自定义标志”在“基本”构建设置中不可见。必须显示“所有”构建设置才能显示。 @EugeneDubinin 可能是因为您应该确保在目标设置中使用$(inherited) 以继承项目设置。 @DanSkeel 很好,添加$(inherited) 使我的评论无关紧要,谢谢! 在 Xcode 8 中,“Swift 编译器 - 自定义标志”部分现在还有一个“活动编译条件”设置。您可以在此处添加标志而无需 -D【参考方案2】:

我们遇到了不想设置 swift 编译器标志的问题,因为我们不想设置它们并让它们针对不同的目标等保持最新。此外,在我们的混合代码库中,我们不希望记住要始终为每种语言适当地设置我们的标志。

对于我们来说,我们在 ObjC 中声明了一个文件

PreProcessorMacros.h

extern BOOL const DEBUG_BUILD;

在.m中

PreProcessorMacros.m

#ifdef DEBUG
    BOOL const DEBUG_BUILD = YES;
#else
    BOOL const DEBUG_BUILD = NO;
#endif

然后,在您的 Objective-C 桥接头中

#import "PreProcessorMacros.h"

现在,在你的 Swift 代码库中使用它

if DEBUG_BUILD 
    println("debug")
 else 
    println("release")

这绝对是一种解决方法,但它解决了我们的问题,所以我在这里发布它希望它会有所帮助。这并不意味着现有的答案是无效的。

【讨论】:

宏的重点是根据构建配置更改代码。您将 if 带回运行时,您不需要宏。 @Berik - 我发布了一个有效的解决方案,希望它也可以帮助其他人尝试解决这个问题的某个方面,特别是在多语言项目中。如果您的问题不需要编译特定代码,那很好。评论也很好,特别是当它教育一些为什么这可能不是他们的解决方案时。还要求在答案中注明这种方法的局限性。投票是不必要的,并且不鼓励可能有助于其他人解决类似问题的替代解决方案。另外,op 说“我不在乎代码是否被编译出来”。【参考方案3】:

Logans 方法更快速的解决方案。在目标的构建设置中的Swift Compiler - Custom Flags 部分的Other Swift Flags 中设置-D DEBUG

然后在全局范围内声明如下方法:

#if DEBUG
let isDebugMode = true
#else
let isDebugMode = false
#endif

现在使用它

if isDebugMode 
    // Do debug stuff

【讨论】:

【参考方案4】:

对我来说,将“Active Compilation Condition”的调试项设置为“DEBUG”即可。

然后在#IF DEBUG 中使用DEBGU 键在调试模式下工作,在发布模式下使用#ELSE:

    选择你的目标, 在 Build Setting 选项卡中搜索“Active Compilation Condition”, 将其“Debug”项的值设置为“YourKeyWord”,

    使用简单如下:

    #if DEBUG
        print("You'r running in DEBUG mode!")
    #else
        print("You'r running in RELEASE mode!")
    #endif
    

【讨论】:

【参考方案5】:

我正在使用混合语言代码库,其中 obj-c 代码使用宏将调试消息发送到控制台(并且该宏依赖于我们的调试预处理器标志)。我希望能够在 swift 代码中调用相同的宏...

    我在我的一个 obj-c 类上创建了一个类方法,它是该宏的包装器。 我将那个 obj-c 头文件添加到我们的桥头文件中。 现在我的 swift 代码将该类方法调用为 obj-c 宏的“代理”。

我不能在 swift 代码中直接调用宏,这有点烦人,但至少现在我在项目中只有一个地方需要担心打开/关闭我的调试标志。

【讨论】:

以上是关于在没有预处理器宏的情况下,有没有办法在 Xcode 项目的项目级别定义实用的方案特定标志的主要内容,如果未能解决你的问题,请参考以下文章

C 预处理器宏参数在末尾带有空格以进行连接?

在构建时添加框架 - XCode

有没有办法创建 Visual Assist 特定的预处理器部分?

Xcode在哪里保存预处理器宏设置

Xcode:测试与调试预处理器宏

使用预处理器宏进行条件编译 Xcode