Xcode 如何在同一源文件中有条件地编译特定于版本的Swift(1.2 vs 2.0)代码?

Xcode 如何在同一源文件中有条件地编译特定于版本的Swift(1.2 vs 2.0)代码?,xcode,swift,compilation,preprocessor,swift2,Xcode,Swift,Compilation,Preprocessor,Swift2,我有一个与我的框架捆绑在一起的Swift演示项目。我想确保演示中的Swift代码能够在没有用户干预的情况下成功地使用Xcode 6(Swift 1.2)和Xcode 7(Swift 2.0)编译 既然存在,我如何在编译时确定使用哪个版本的Swift或Xcode来编译代码 现在,这里是重要的细节: 它必须自动工作! 在Xcode 6->compiles中打开项目 Swift 1.2代码 在Xcode 7->编译Swift中打开项目 2.0代码 没有生成设置或其他方式要求用户以某种方式指定她

我有一个与我的框架捆绑在一起的Swift演示项目。我想确保演示中的Swift代码能够在没有用户干预的情况下成功地使用Xcode 6(Swift 1.2)和Xcode 7(Swift 2.0)编译

既然存在,我如何在编译时确定使用哪个版本的Swift或Xcode来编译代码

现在,这里是重要的细节:

  • 它必须自动工作!
    • 在Xcode 6->compiles中打开项目 Swift 1.2代码
    • 在Xcode 7->编译Swift中打开项目 2.0代码
没有生成设置或其他方式要求用户以某种方式指定她使用的Swift/Xcode版本

我一直在想:这是一项如此琐碎的任务,用Swift怎么可能做不到呢

作为一名框架开发人员,这让我抓狂,因为Swift项目的成功编译现在完全取决于用户的Xcode版本,我不能要求他们都“更新到Xcode 6.4”,以后不得不再次要求他们“更新到Xcode 7.1”。这太疯狂了

当然,另一种选择是有单独的演示项目,管理不同的代码库,每个版本对应一个Swift。并希望用户知道什么项目将与她的Xcode版本一起工作。不是真正的选择


不幸的是,另一种选择,就是不使用Swift 2.0的任何增强功能。有些语法、类和方法在一个或另一个Swift版本中不起作用,如果只是因为编译器在较新的Xcode版本中更挑剔的话。

在项目中有两个版本的代码将不起作用,因为代码不会编译。没有用于基于版本的条件编译的编译器指令

有一个解决方案可以工作(没有测试)

首先创建名为version\u current.swift、version\u 1\u 2.swift和version\u 2.swift的3个文件。确保您的构建目标中只包含当前的.swift版本

然后创建一个新的构建脚本阶段,并将其放在“编译源代码”阶段的正上方。在该脚本中,您将在当前脚本上复制1_2或2版本的内容

我的脚本知识不是很好,所以我不能给你很多帮助。您可以使用以下代码获取版本:

$ xcrun swift -version
然后执行一个copy语句


但这只适用于系统上的默认Xcode版本。如果要使用其他版本,还必须更改默认版本

您可以使用Xcode的一些高级构建设置来实现这一点,特别是:

  • XCODE\u VERSION\u MAJOR
    :将XCODE主要版本编码为类似“0700”的字符串
  • EXCLUDED\u SOURCE\u FILE\u name
    :默认情况下要排除的源文件的“fnmatch”样式模式
  • INCLUDED\u SOURCE\u FILE\u name
    :要包含的源文件的“fnmatch”样式模式
我一般不建议这样做,因为这会让大多数Xcode用户难以理解您的项目,但是如果您确实想让它工作,您可以使用这种技术

您完成此任务的方式如下所示:

  • 对于任何需要进行版本控制的源文件,请将其命名为“Thing-versioned-0600.swift”和“Thing-versioned-0700.swift”。确保两个文件都处于源代码生成阶段

  • 通过添加项目级生成设置,使用排除机制防止默认情况下编译任何版本化文件:
    excluded\u SOURCE\u FILE\u NAMES=*-versioned-*.swift

  • 通过添加另一个项目级生成设置,使用包含机制仅添加回与当前Xcode主要版本匹配的文件:
    included\u SOURCE\u FILE\u NAMES=*-Versioned-$(Xcode\u version\u major).swift


  • 我甚至不知道这怎么可能。这里有一些重要的语法变化和逻辑变化。这在任何一种像样的语言中都非常简单:您只需基于编译器/系统库提供的定义或其等效定义进行ifdef。唉,斯威夫特给出了%&§$!在Swift中,即使是#if/#else/#endif的“非活动”部分也必须在语法上有效,因此我认为这是不可能的。类似/相关:,.Unity3D经常这样做,但从我在7.4测试版笔记中读到的内容来看,我觉得它不会尊重这样的东西。他们甚至还没有变量名重构……即使这是可能的(我现在不相信),我认为最终在一个代码库中维护两个代码库的时间将超过在Xcode 6或7中编译所增加的灵活性。我的建议是坚持使用Swift 1.2,直到您可以完全跳转到Swift 2/Xcode 7。