在没有预处理器宏的情况下,是否有一种方法可以在Xcode项目的项目级别上定义实用的方案特定标志


174

在快速介绍之前,我将为Alpha,Beta和发行版构建定义一套方案。这些方案中的每一个都有一组宏,这些宏被定义为在项目级别上控制某些行为。最简单的示例是DEBUG = 1宏,默认情况下,该宏是针对运行构建的默认方案中的所有Xcode项目定义的。可以查询#ifdef DEBUG ...并相应地在代码中做出决定,甚至可以编译出不必要的代码。

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

Answers:


468

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

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

现在,您必须在其他位置设置“ DEBUG”符号。在“ Swift编译器-自定义标志”部分的“其他Swift标志”行中进行设置。您将DEBUG符号与-D DEBUG条目。

(构建设置-> Swift编译器-自定义标志) 在此处输入图片说明

与往常一样,在“调试”或“发行”中可以设置其他值。

我用真实代码进行了测试;它似乎在操场上未被认可。


5
请注意,您还可以使用#elseif行添加更多测试。有趣的是,您可以访问定义,但不从中提取任何内容。也就是说,定义-DDEBUG = 5(或=“FOO”),然后尝试用它打印“的println(DEBUG是(DEBUG)”那行不产生任何错误,但不会做任何事情。
David H制作

10
注意:在“基本”构建设置中看不到“内置设置-> Swift编译器->自定义标志”。必须显示“所有”构建设置才能显示。
levibostian

7
@EugeneDubinin可能是因为您应确保$(inherited)在目标设置中使用它来继承项目设置。
DanSkeel 2015年

2
@ DanSkeel很好,添加$(inherited)使我的评论无关紧要,谢谢!
Yevhen Dubinin

10
在Xcode 8中,“快速编译器-自定义标志”部分中现在还有一个“活动编译条件”设置。您可以在此处添加标志,而无需-D
Marcus

32

我们遇到了一个问题,就是不想设置快速的编译器标志,因为我们不想设置它们并保持它们针对不同目标的最新状态。此外,在我们的混合代码库中,我们不想记住为每种语言始终设置适当的标志。

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

PreProcessorMacros.h

extern BOOL const DEBUG_BUILD;

在他们之中

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")
}

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


11
宏的全部要点是根据构建配置更改代码。您将if返回到运行时,则不需要宏。
Berik

18
@Berik-我发布了一个有效的解决方案,希望它也可以帮助其他尝试解决此问题的方面,尤其是在多语言项目中。如果您的问题不需要编译特定的代码,那很好。评论也很好,特别是当它教了一些为什么这可能不是他们的解决方案时。还要求在答案中记录有关此方法的局限性。减少投票是不必要的,并且不鼓励其他解决方案,这些解决方案可能会对其他解决类似问题的人有所帮助。另外,op说“我不在乎代码是否已编译”。
洛根

5

更快速地解决Logans方法。坐落-D DEBUGOther Swift FlagsSwift Compiler - Custom Flags在你的目标的构建设置部分。

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

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

现在将其用作

if isDebugMode {
    // Do debug stuff
}

1

对我来说,将“ 活动编译条件 ” 的调试项设置为“调试”。

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

  1. 选择您的目标,
  2. 在“构建设置”选项卡中搜索“活动编译条件”,
  3. 将其“调试”项的值设置为“ YourKeyWord”,
  4. 使用简单如下:

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

0

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

  1. 我在一个obj-c类中创建了一个类方法,该方法是该宏的包装器。
  2. 我将obj-c标头添加到我们的桥头文件中。
  3. 现在,我的快速代码将该类方法称为obj-c宏的“代理”。

我不能只在快速代码中直接调用宏,这有点令人讨厌,但是至少现在我在项目中只有一个位置担心打开/关闭调试标志。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.