iOS开发里的CocoaPods

工作上的一个项目需要自己本地构建,所以稍微了解了一些。

什么是CocoaPods

  1. 为 iOS 程序提供依赖管理的工具,开始于 2011年8月12日,经过多年发展,现在已经成为iOS开发事实上的依赖管理标准工具。
  2. 只需要一个Podfile文件,就能通过命令pod install完成以前复杂的工作:
    1. 第三方开源库的源代码文件复制到项目中,或者设置成 git 的 submodule
    2. 这些开源库通常需要依赖系统的一些 framework,开发者需要手工地将这些 framework 分别增加到项目依赖中,比如一个网络库就需要增加以下 framework: CFNetwork, SystemConfiguration, MobileCoreServices, CoreGraphics, zlib。
    3. 某些开源库,还需要手动设置-licucore或者-fno-objc-arc等编译参数
    4. 需要关注依赖包的更新

CocoaPods的原理

  1. 依赖库会被放到一个名为Pods的项目里(看起来就是一个文件夹)然后主项目依赖于它。
  2. Pods项目最后会编译成一个名为libPods.a的文件,主项目里引用的就是它
  3. 对于资源文件,CocoaPods 提供了一个名为 Pods-resources.sh 的 bash 脚本,该脚本在每次项目编译的时候都会执行,将第三方库的各种资源文件复制到目标目录中。
  4. CocoaPods 通过一个名为Pods.xcconfig的文件来在编译时设置所有的依赖和参数。

CocoaPods的安装和使用

Ruby环境

  1. ruby环境参考其他文章
  2. gem可能需要更新gem update --system

安装CocoaPods

  1. 一般来讲,需要换国内镜像,比如淘宝的,或者https://gems.ruby-china.com/
    1. gem sources -l可以查看现在的源
    2. gem sources --remove https://rubygems.org/
    3. gem sources -a http://ruby.taobao.org/
    4. 注意:,很多网上的老文章,写的都是https://gems.ruby-china.org/,但是这个镜像地址已经改成了.com
  2. gem install cocoapods
  3. 如果需要安装beta版本,就是gem install cocoapods --pre

截止2018-10,发现pod的一个bug

  1. 1.6.0 beta2修复了一个问题,就是在project.pbxproj文件里,老pod(比如1.2,1.4版本)会在pod install的时候生成一些代码,比如下面这样:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    16162FB2E14A1C2A5D2BD828 /* [CP] Embed Pods Frameworks */ = {
    isa = PBXShellScriptBuildPhase;
    buildActionMask = 2147483647;
    files = (
    );
    inputFileListPaths = (
    );
    inputPaths = (
    );
    name = "[CP] Embed Pods Frameworks";
    outputFileListPaths = (
    );
    outputPaths = (
    );
    runOnlyForDeploymentPostprocessing = 0;
    shellPath = /bin/sh;
    shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SHInvest/Pods-SHInvest-frameworks.sh\"\n";
    showEnvVarsInLog = 0;
    };
  2. 然后把这些改动在Git提交了,那么其他人在pod install的时候就会遇到报错——新版本的pod会删掉这段代码。

  3. 进一步谈一下文件project.pbxproj的Git管理问题,这里有一些改动是需要提交的,但是pod install带进来的改动,是没有必要提交的。所以一般的处理是使用Git命令去忽略pod install带来的改动,只提交项目里需要跟踪的改动。

CocoaPods初始化

  1. pod setup
  2. 所有的项目的 Podspec 文件都托管在一个github的项目上。第一次执行setup时,CocoaPods会将这些podspec索引文件更新到本地的~/.cocoapods/目录下,这个索引文件比较大,有 300多M 左右,在执行一次pod install之后这个文件目录还会增加到700多M。所以第一次很慢是正常的,不要慌,建议提前预留时间,比如下班前执行,明天来收获
  3. 整个过程比较慢,可以查看目录下(~/.cocoapods/)文件的大小du -sh *,以此检查进度
  4. 下载索引可以换一个镜像:

    1
    2
    3
    pod repo remove master
    pod repo add master https://gitcafe.com/akuandev/Specs.git
    pod repo update

CocoaPods在项目中

  1. 在项目根目录下建立Podfile,写入你需要引用的各种库,比如pod 'WechatOpenSDK',还可以添加版本设定,比如pod "AFNetworking", "~> 2.0"
  2. 一般来说,类库的原作者会告诉你导入该类库应该如何写Podfile
  3. Podfile里不仅可以罗列,还可以写入各种逻辑,比如私有库的地址配置,比如管理开发/生产模式下的库的引用、版本控制等
  4. 首次安装依赖:pod install
  5. 默认会增加一个文件夹Pods来存放安装的依赖包,当然也可以在Podfile里设置,用别的文件夹存放一些私有库之类的。
  6. 之后,打开工程文件应该使用CocoaPods生成的.xcworkspace而不是项目里原先的.xcodeproj文件。

CocoaPods安装依赖

  1. 可以直接通过命令来搜索库,pod search <关键字>
  2. Podfile.lock用于锁定当前各种依赖库的版本。首次install之后生成,之后install都会按照这个文件锁定的版本来
  3. 更改了Podfile之后,在有lock文件存在的情况下,应该通过pod update命令来更新依赖包

私有pods

CocoaPods还支持管理私有的pod,比如公司内部的pod,或者把项目中一些模块写成pod的形式来引入。特别在一个app包含多条业务线的时候,就可以这么架构,让不同的业务线成为不同的pod,主体App和业务线的独立开发将会更加容易。


用户的spec资源配置信息和它们的更新

本地的spec资源配置

  1. 之前提过,在安装CocoaPods后,首次使用需要setup,这其实是去生成了一个本地的spec资源配置信息,本质就是官方管理所有pod库的一个资源库的拷贝。
  2. 文件夹.cocoapods一般在用户的目录下,比如/Users/<user>/.cocoapods/repos/master/Specs/<lib name>这样子的,里面分版本包含多个文件夹,文件夹里是json文件,包含了那个库的一些信息,比如作者、许可协议、版本、资源地址等等
  3. 命令pod install其实就是根据pod库名在上面的文件夹里找对应的库,如果指定了版本就找到指定版本的.podspec,否则就找最高版本的.podspec,然后根据文件里的配置里的资源地址去下载。
  4. 如果本地的.cocoapods文件夹里找不到相应的配置文件,那么库就无法安装。比如某个库安装的是最新的,不通过update的话就找不到那个版本。

本地的spec的更新

  1. 现在pod update其实就会默认执行一遍pod repo update——也就是说这个命令先更新了一遍索引才去下载新的。
  2. pod repo update会更新整个.cocoapods文件夹下的所有库,有时候可能不太快。
  3. 可以单独更新某个库pod repo update /Users/<user>/.cocoapods/repos/master/Specs/<lib name>,这个命令在你需要单独更新某个私有库的时候就很有用了。
  4. 甚至可以手动增加配置文件,去那个库的git上找到相应的文件然后手动增加,比如/Users/<user>/.cocoapods/repos/master/Specs/<lib name>/3.2.0/<lib name>.spec

避免长时间的更新

  1. 如上所述,如果在Podfile里没有指定pods的版本号,那么每当执行pod update的时候,都会更新索引,然后尝试拉取类库的最新版本,这就很麻烦了
  2. 如果没有指定好pods的版本号,但是又不希望每次都更新到最新,那么在修改了部分pods配置后,更新pods的最好方法是pod update --no-repo-update,这样就只根据本地索引跟新,不会去拉远程spec

把自己的类库用Cocoapods管理

生成podspec文件:pod spec create <your_pod_spec_name>,执行后生成名为your_pod_spec_name.podspec的文件。