在 ABI 稳定后发展 Apple 平台上的 Swift
随着 Swift 5.0 的发布,Swift 现在 ABI 稳定,并作为 macOS、iOS、tvOS 和 watchOS 的核心组件交付。ABI 稳定性自 Swift 诞生以来一直是其目标,并为这些平台的开发者和用户带来了诸多益处
- 最明显的是,用 Swift 编写的应用程序不再需要与 Swift 运行时库一起分发,从而减小了下载大小。
- Swift 运行时可以与这些主机操作系统更深入地集成和优化,从而使 Swift 程序启动更快、获得更好的运行时性能并使用更少的内存。
- Apple 将能够在未来的操作系统中使用 Swift 交付平台框架。
- 当未来版本的 Swift 也提供 模块稳定性 时,第三方也将能够发布用 Swift 编写的二进制框架。
然而,正因如此,Swift 运行时现在是用户目标操作系统的一个组件,而不是开发者工具链的一部分。因此,在未来,为了让 Swift 项目采用新的 Swift 运行时和标准库功能,它可能还必须要求包含支持新增功能的更新 Swift 运行时的新的操作系统版本。采用新的语言特性和框架或保持与旧操作系统版本兼容性之间的这种权衡,对于 Objective-C 和 Apple 系统框架来说一直存在,现在也将成为 Swift 的一个因素。
哪些类型的语言特性和演化提案可能会受到未来操作系统版本的限制?
任何需要新的 Swift 运行时或标准库支持的功能都可能受到操作系统可用性限制。这包括
- 对标准库的添加,包括新的类型、协议、协议一致性、函数、方法或属性。
- 对 Swift 类型系统的更改,例如新的类型种类、现有类型的新修饰符(例如函数类型属性)、新的桥接、子类型和/或动态转换关系等。
核心团队将在审查新提案时考虑其向后兼容性影响。
ABI 稳定性是否会影响我使用 Swift 4.0 或 4.2 模式来保持与现有代码的源代码兼容性的能力?它是否会影响我将来更改为新的语言模式的能力?
不会。语言兼容性设置纯粹是一个编译时特性,用于控制源代码兼容性。它不影响 ABI。您无需将 Swift 4 代码迁移到 Swift 5 模式即可使用 Swift 5 的稳定 ABI,并且展望未来,如果未使用需要新运行时功能的语言特性,则可以在不施加更新操作系统要求的情况下采用新的语言模式。
我是否必须使用 Xcode 10.2 重新编译现有的 Swift 应用程序才能在最新的操作系统上运行?
捆绑了 Swift 运行时库的现有 Swift 二进制文件将继续在 macOS 10.14.4、iOS 12.2、tvOS 12.2、watchOS 5.2 和未来的操作系统版本上运行。这些应用程序将继续使用其捆绑的 Swift 运行时运行,因为这些较旧的 Swift 运行时与稳定的 Swift ABI 不兼容。操作系统中的 Swift 运行时旨在相互忽略任何捆绑的 Swift 运行时,因此它会将应用程序捆绑的 Swift 运行时定义的类视为普通的 Objective-C 类,并且捆绑的 Swift 运行时同样会将来自操作系统的 Swift 类视为普通的 Objective-C 类。但是,使用捆绑运行时的应用程序将无法获得 App Store 应用程序精简的好处。
用 Swift 5 构建的应用程序是否可以在 macOS 10.14.4 之前的任何版本上运行?
Swift 5 不要求应用程序提高其最低部署目标。
部署回早期操作系统版本的应用程序将在其内部嵌入 Swift 运行时的副本。当在附带 Swift 运行时的操作系统版本上运行时,这些运行时的副本将被忽略——实际上是惰性的。
我可以选择捆绑更新的 Swift 运行时到我的应用程序中,以便能够使用新的运行时功能而无需新的操作系统吗?
由于多种原因,这将是不可能的
- 用于维护与稳定前 Swift 运行时兼容性的共存功能取决于单个进程中活动的 Swift 运行时不超过两个,并且所有使用稳定前运行时的 Swift 代码都作为应用程序的一部分是自包含的。如果使用相同的机制来允许捆绑较新的 Swift 运行时与操作系统 Swift 运行时并行运行,则新的运行时将无法访问操作系统中的 Swift 库或链接到操作系统运行时的 ABI 稳定第三方 Swift 库。
- 完全替换操作系统运行时将规避系统库的安全性,这些系统库的签名是基于它们使用操作系统版本的运行时。
- 此外,如果可以替换操作系统 Swift 运行时,这将为操作系统、Swift 运行时以及第三方库和应用程序都必须针对其进行测试的配置矩阵增加一个维度。“DLL 地狱”之类的状况会使测试、鉴定和交付代码变得更加困难和昂贵。
- 通过位于操作系统中,Swift 运行时库可以与其他操作系统组件紧密集成,特别是 Objective-C 运行时和 Foundation 框架。操作系统运行时库也可以合并到 dyld 共享缓存中,这样与共享缓存之外的 dylib 相比,它们具有最小的内存和加载时间开销。最终,在操作系统外部构建的运行时可能无法完全复制操作系统运行时的行为,或者这样做可能会在约束为使用稳定 API 时带来显着的性能成本。
是否可以做些什么来允许将对新 Swift 功能的运行时支持向后部署到旧版本的操作系统?
某些类型的运行时功能可能可以向后部署,可能使用诸如在应用程序中嵌入“垫片”运行时库之类的技术。但是,这并非总是可能。成功向后部署功能的能力从根本上受到旧操作系统中已发布的二进制工件的限制和现有错误的约束。核心团队将在审查新提案时逐案考虑其向后部署的影响。