CocoaPods 1.7.0 Beta!

CocoaPods 1.7.0 大幅扩展了早期版本中改进的基础设施,支持多个 Swift 版本、应用规范等!

这是一个包含各种新功能的大版本,有助于推动 CocoaPods 的发展。

让我们直接开始吧!

支持多个 Swift 版本

最早在 CocoaPods 1.4.0 中引入的 swift_version DSL 现已扩展为支持多个 Swift 版本。这有助于 Pod 作者,并为消费者在使用 Pod 时选择哪个 Swift 版本提供了更大的灵活性。

Pod 作者现在可以通过在 swift_versions DSL 中指定其他 Swift 版本,将该信息转录到其 podspec 中。

以下是一个指定其支持的其他 Swift 版本的 podspec 示例

Pod::Spec.new do |spec|
  spec.name = 'CoconutLib'
  spec.version = '1.0'
  # ... rest of root spec entries go here
  spec.swift_versions = ['3.2', '4.0', '4.2']
end

除非 CoconutLib Pod 的消费者另行指定,否则 CocoaPods 将在安装期间自动选择最新版本的 Swift,在本例中为 4.2

但是,在很多情况下,Pod 的消费者可能无法使用最新版本的 Swift,可能是因为他们的工具链还不支持它。例如,使用不支持 Swift 4 的较旧版本 Xcode 的项目将无法集成 CoconutLib Pod,并最终导致编译错误。为了解决此问题,CocoaPods 1.7.0 提供了通过新的 supports_swift_versions DSL 为 Podfile 中集成的每个目标指定 Swift 版本要求的功能。

例如

target 'MyApp' do
  supports_swift_versions '>= 3.0', '< 4.0'
  pod 'CoconutLib', '~> 1.0'
end

上述配置将成功集成 CoconutLib Pod,并使用 Swift 3.2 作为编译它的版本。这是因为它是在 MyApp 目标定义中指定的条件和 CoconutLib podspec 中声明的支持的 Swift 版本列表中唯一满足条件的版本。

注意supports_swift_versions DSL 也可以在 Podfile 的根级别声明,在这种情况下,它将应用于 Podfile 中的所有目标。此外,嵌套目标(例如测试目标)将从其父级继承其 Swift 要求,除非它们明确指定自己的 Swift 版本要求。

在选择要使用的 Swift 版本时,还有许多其他可能发生的边缘情况。我们鼓励您阅读此更改的 提案 以了解更多信息!

Linting 和验证

对于 Pod 作者来说,维护基础设施以支持多个(主要是较旧的)Swift 版本通常很困难,因此,在 lint 期间,CocoaPods 将在验证期间选择 Swift 的最新版本。

对于确实拥有基础设施(例如 CI 系统)以确保其 Pod 与较旧版本的 Swift 配合使用的 Pod 作者,应在 lint 期间使用 --swift-version 参数来覆盖默认行为。

弃用 .swift-version 文件

到目前为止,大多数 Pod 作者一直依赖于在仓库根目录中指定一个 .swift-version 文件,以便使用他们正式支持的 Swift 版本成功发布他们的 Pod。然而,此信息从未在已发布的 podspec 中转录,因此在集成期间,在选择要使用的 Swift 版本时不会考虑任何信息。

这可能会导致很多问题,尤其是在发布新版本的 Swift 时。这是因为使用者会自动选择要使用的最新版本的 Swift,而 Pod 作者并未正式声明支持它。

我们强烈建议 Pod 作者迁移到在 podspec 中使用官方支持的 swift_version DSL。

我们还建议删除仓库中的 .swift-version 文件,除非将其用于其他工具,例如 swiftenvswift_version DSL 将始终优先于 .swift-version 文件。

最后,在 lint 期间将显示一条警告,鼓励 Pod 作者不再使用 .swift-version 文件,并且在 CocoaPods 的未来主要版本中,我们计划完全取消对它的支持。

应用规范

借助最近引入的 测试规范,我们能够构建一个平台,以便我们扩展并引入 Pod 作者可以提供的不同类型的规范。在 1.7.0 中,我们引入了应用规范,它允许 Pod 作者在 podspec 中描述一个应用程序。

应用规范可以帮助 Pod 作者以各种方式,例如,它们可以用来随 Pod 一起发布一个示例应用,作为使用者如何将其集成到各自应用中的教程。

应用规范推进了“隔离开发”的概念,其中 podspec 可用作生成整个(可抛出的)工作空间以进行开发所需的信息。

以下是一个应用规范声明的示例

Pod::Spec.new do |s|
  s.name         = 'CoconutLib'
  s.version      = '1.0'
  s.authors      = 'Coconut Corp', { 'Monkey Boy' => '[email protected]' }
  s.homepage     = 'http://coconut-corp.local/coconut-lib.html'
  s.summary      = 'Coconuts For the Win.'
  s.description  = 'All the Coconuts'
  s.source       = { :git => 'http://coconut-corp.local/coconut-lib.git', :tag => 'v1.0' }
  s.license      = {
    :type => 'MIT',
    :file => 'LICENSE',
    :text => 'Permission is hereby granted ...'
  }

  s.source_files = 'Sources/*.swift'

  s.app_spec 'SampleApp' do |app_spec|
    app_spec.source_files = 'Sample/*.swift'
  end  
end

应用程序规范可以利用 CocoaPods 规范 DSL 的大多数功能来声明依赖项、构建配置设置等。

默认情况下,应用程序规范不会自动集成到使用 pod 的项目中。如果您希望这样做,可以在 Podfile 中指定此项,类似于测试规范

 target 'MyApp' do
   use_frameworks!
   pod 'CoconutLib', '~> 1.0', :appspecs => ['SampleApp']
 end

我们希望在未来将应用程序规范提升为一个顶级概念,其中消费者应用程序被描述为一个应用程序规范,完全消除了维护 .xcodeproj 以与 CocoaPods 集成的需要。

多 Xcodeproj 生成

从历史上看,CocoaPods 一直生成一个包含项目编译所需的所有目标和构建设置的 Pods.xcodeproj。仅使用一个包含整个 Podfile 的项目对于较小的项目来说工作得很好;但是,随着项目的增长,Pods.xcodeproj 文件的大小也会增长。

Pods.xcodeproj 文件越大,Xcode 花在解析其内容上的时间就越长,我们发现这会导致 Xcode 体验下降。我们注意到,与其将所有目标都放入一个单一的 Xcode 项目中,不如将每个 pod 集成到它自己独立的 Xcode 项目中,并嵌套在顶级 Pods.xcodeproj 下,这样可以为大型 CocoaPods 项目带来相当大的性能提升。

此外,在大型代码库中,此功能可能特别有用,因为开发人员可以选择仅打开他们需要处理的特定 .xcodeproj(在 Pods/ 目录下找到),而不是打开整个工作区,这可能会减慢他们的开发过程。

无论性能是否成为问题,或者您只是更喜欢使用多个 Xcode 项目来设置工作区,CocoaPods 现在都支持使用 generate_multiple_pod_projects 安装选项来设置此项。

您可以在 Podfile 中像这样启用它

install! 'cocoapods', :generate_multiple_pod_projects => true

默认情况下,此选项处于关闭状态,但我们鼓励您试用它并向我们报告您发现的任何问题。我们预计在未来 CocoaPods 的重大版本更新中,当涉及到工作区生成时,这将成为默认选项。

以下是它的样子

没有多 Xcodeproj(默认):

带有多 Xcodeproj:

警告:如果您将项目切换为使用多个 .xcodeproj,如果您的 pod 依赖于使用引号语法导入其依赖项的标头,则可能会导致一些编译器错误。例如,#import "PDDebugger.h" 将不再适用于依赖于 PonyDebugger 的 pod 中。相反,我们强烈建议您更新标头以正确导入框架及其关联标头:#import <PonyDebugger/PDDebugger.h>。这是故意的,因为此功能当前是可选择加入的。

增量安装

现在,CocoaPods 不再每次运行 pod install 时重新生成整个工作区,而是仅重新生成自上次安装以来已更改的 pod 目标。根据项目的大小,这可以为每次 pod install 调用节省几秒到几分钟的时间。

您可以在 Podfile 中使用安装选项 incremental_installation 来启用此功能,如下所示

install! 'cocoapods',
         :generate_multiple_pod_projects => true,
         :incremental_installation => true

注意incremental_installation 选项当前需要 generate_multiple_pod_projects 安装选项也已启用才能正常运行。

scheme DSL

Pod 作者现在可以自定义其规范、测试规范和新发布的应用规范的生成方案。目前,包括指定环境变量和启动参数的支持,并且将来可以轻松扩展。

以下是一个示例

Pod::Spec.new do |spec|
  spec.name = 'CoconutLib'
  spec.version = '1.0'
  # ... rest of root spec entries go here
  spec.test_spec 'Tests' do |test_spec|
    test_spec.source_files = 'Tests/**/*.swift'
    test_spec.scheme = { 
      :launch_arguments => ['Arg1', 'Arg2'], 
      :environment_variables => { 'Key1' => 'Val1'}
    }
  end
end   

上述示例将为测试规范 Tests 生成以下方案

注意:您可以选择为特定平台配置方案。例如,test_spec.ios.scheme 将仅为 iOS 目标配置方案。

.xcfilelist 支持

在 CocoaPods 1.7.0 中,脚本阶段现在支持使用 .xcfilelist 来指定脚本输入和输出路径。CocoaPods 将自动检测正在集成的 Xcode 项目是否支持 .xcfilelist,并优先于单独的输入/输出路径条目。

这减少了 CocoaPods 在用户项目中的占用空间,但也利用了针对每个配置(例如“调试”与“发布”)使用不同的输入/输出路径的能力。

实验性功能

随着 1.7.0 的发布,我们提供了一些令人兴奋且重要的实验性功能!

主规范存储库的 CDN 支持

主规范存储库对于 CocoaPods 的功能至关重要,然而,多年来它的规模急剧增长,成为使用 CocoaPods 的首要困难。

对于互联网连接速度慢的人来说尤其如此,因为克隆存储库及其整个历史几乎是不可能的。此外,由于克隆可能需要很长时间,因此 CI 系统的首次设置也会大大减慢。

在 1.7.0 中,我们正在尝试使用 CDN 支持来避免在本地计算机(或 CI)上克隆 主规范存储库 以便使用 CocoaPods。可以通过用以下内容替换 Podfile主规范存储库 声明的 source 来启用此功能

# source 'https://github.com/CocoaPods/Specs' comment or remove this line.
source 'https://cdn.jsdelivr.net.cn/cocoa/'

或者,您可以通过运行 pod repo remove master 删除现有的基于 git 的存储库。

我们预计语法或服务器结构将在 1.8.0 中再次更改,因此在 1.7.0 中采用此功能时,您应该预计将来必须进行更改以保持此功能正常工作。我们不打算在 1.7.x 版本之外支持 1.7.0 版本。

我们要感谢 jsDelivr 的支持和帮助,让这项工作得以实现!目前,我们计划同时维护这两种使用 主规范存储库 的方式,但我们强烈建议您进行切换,因为这可以更快地开始使用 CocoaPods。

根据结果和稳定性,我们希望从 1.7.0 开始,CocoaPods 将不再要求用户克隆 主规范存储库 即可开始使用。

Windows 支持

从 1.7.0 开始,我们增加了对 Windows 的支持!我们鼓励 Windows 用户使用 CocoaPods,并 向我们报告任何问题

接下来是什么?

CocoaPods 1.7.0 是一个非常令人兴奋的版本,我们非常高兴您能够试用它,并建议您升级

$ gem install cocoapods --pre

对于未来版本,我们希望大幅改善 CocoaPods 的集成故事。

目前,Pod 的使用者在集成他们的项目时仅限于全有或全无的方法,迫使他们通过 use_frameworks! 选项选择在所有地方使用动态框架还是在所有地方使用静态库。

另一方面,Pod 作者在指定其 Pod 如何打包并链接到使用者目标的选项方面也非常有限,并且必须确保其 Pod 可以跨不同排列的包和链接样式进行编译。我们正处于规划阶段的早期,思考如何进一步改进这一点,并为 Pod 作者和使用者提供更好的选择。

一如既往,我们要感谢我们所有的贡献者,让此版本成为现实!

查看 变更日志 以获取完整变更列表。

🚀