[iOS] CocoaPods相关

这个部分首先先大概说下pod的一些基本概念~ 然后过一下如果拆分模块的pod。(这篇也是和同事学习的QAQ)

起源 & Gemfile

在没有pod之前其实我们是直接拷贝源码的:


pod之前

有了pod之后我们可以用pod来引入依赖,避免了手动的繁琐。pod其实是借鉴Bundler(基于ruby的集成工具,对应的是GemFile),cocoapods其实也属于ruby的一个组件。

ruby和pod

所以其实Gemfile和它的lock文件就是锁死了我们工程所需要的gem环境,例如哪些ruby的工具,cocoapods的版本、fastlane的版本、所需要的插件们~


原理
pod流程

我们在podfile里面写明我们所依赖的库名,install的时候,pod会从source里面所有的spec repo里面去找到我们要的库的podspec文件,然后通过这个文件里面的url找到我们的库,再download下来。

pod setup做的事情其实就是把远端的podspec文件们都clone到本地。

pod updatepod install的区别?
pod install如果你不改podfile,那么每次都是一样的;但是pod update它会先执行pod repo update把repo拉一下,如果库升级了,那么会就去下载最新的库,然后更新.lock文件里面的版本。pod update还可以升级某个指定的库~


Pod命令解析过程
pod的组件们
  • 命令分析就是解析我们输入的例如pod install命令
  • 依赖解析算法就类似我们会在podfile里面规定很多依赖的库,但这些库也会依赖别的库,pod里面规定的其实是一个子集,如何保证引用的库不会产生版本冲突,就是这个模块负责检查的(例如A依赖1.0的B,C依赖2.0的B)
    P.S 编译的时候会先编译最底层被依赖的库,例如A依赖B,那么就会先编译B生成B的.a文件,然后在编译A
  • 工程生成模块其实就是生成那个小白色的工程文件哒(Pods会生成一个工程,我们原工程也有一个工程,所以这个xcworkspace是为了组织这两个工程)

Pod文件
关键文件

Podfile.lock是第一次install生成的文件(如果当前木有lock文件),除非podfile变化或者执行了pod update否则是不会变的。

它记录了需要被安装的 pod 的每个已安装的版本,当团队中的某个人执行完pod install命令后,生成的Podfile.lock文件就记录下了当时最新Pods依赖库的版本,这时团队中的其它人check下来这份包含Podfile.lock文件的工程以后,再去执行pod install命令时,获取下来的Pods依赖库的版本就和最开始用户获取到的版本一致

如果没有Podfile.lock文件,后续所有用户执行pod install命令都会获取最新版本的依赖库,这就有可能造成同一个团队使用的依赖库版本不一致。

由于sandbox,也就是pods目录是不由git管理的,那么怎么知道要不要更新本地库呢?在每次pod install的结束的时候,会自动复制一份Podfile.lock复制到Manifest.lock。每次build的时候会执行xcode里面设置的脚本,比较Podfile.lockManifest.lock的md5,如果不一致就会报错the sandbox is not in sync with the podfile.lock. run 'pod install' or update your cocoapods

每个库都会生成一个.a的framework文件,pods的project会依赖这些.a文件,然后pods的project也会生成一个总的.a文件,我们自己的porject会引用pods的.a文件:

.a依赖

headers这个目录就是所有组件对外public的头文件~ 并且生成xcode的时候会自动在xcode的build settings增加这个search path。

repos文件夹其实是为了防止每次库依赖分析以及install都去访问github的spec,所以在本地clone了一个~ 由于外网pod更新非常频繁,所以有些公司都是自己做的内网映射,保证源不会经常更新,避免经常pod update。如果遇到报错找不到某个版本,但是git上是有的,执行以下pod repo update更新一下源即可。

cache是每次pod install的库文件的cache,如果其他工程也恰好需要同样的版本,就可以直接拿copy给它用啦,避免了下载的操作。

P.S. 一个版本的~>只是末位可以大于,前面的数字还是要保持一致的,例如1.0.2 ~> 1.0.1,但是1.1.2 ~> 1.0.1是不成立的。


Podfile黑技巧
podfile的参数

podfile里面可以通过类似key-value的方式设置一些值~

clean的意思就是install的时候,如果有些库没有用到会清理;share_schemes_for_development_pods是不是把pod target设置为share;generate_multiple_pod_projects是将pod生成多个project,工程可以动态检索文件,这样每个pod都是一个project,在build的时候就会动态获取文件,避免了向本地dev pod增加文件,但是编译的时候找不到文件,还必须要pod install以后才可以;incremental_installation是多project的模式下增量install,当pull代码以后podfile可能会有改变,加入这个参数以后会cache上次的install结果,只有cache版本不一致才会重新走install(下载 & 生成pod target)的流程。

如果有多个source,然后都有同一个库,版本号还一致,但是库实际文件不一样,那么pod会按顺序找到第一个版本拿到然后用,所以不同source如果同一个库内容不一样但版本号还一样就容易出bug。


hook

pre_installpost_install也就是pod的开始以及结束,是可以用脚本注入做一些事情的。podfile其实就是一个ruby脚本,可以在里面做一些hook。

hook

Podfile的编写
podfile示例

spec的外部引用就是通过path、git、commit之类描述的依赖,也就是除了用版本号规定的都是,它会根据文件里面找到的版本号加到版本分析的树里面~

subspec的意思就是只依赖AFNetworking里面的NSURLSession这个小一点的模块。


Podspec文件编写 —— 生成自己的库
podspec

具体代码如何做参考这个吧:https://zhuanlan.zhihu.com/p/37843887 & https://www.jianshu.com/p/1dabeb10c33a

关于本地私有库可以这么做:https://www.cnblogs.com/hs-funky/p/6759977.html

用本地库的方式就是在项目内建一个文件夹,用于放各个模块的代码(如果之前xcode对这些文件有索引可以删掉),然后给他们按照上面的文章里面生成pod(pod spec create 模块名),然后编写pod spec文件,之后修改本项目的podfile,引用这个本地库通过path的方式,最后pod install,这个时候xcode是没有这个库里面的文件的索引的,只有pod有,你会在Development Pods里面看到这个模块,你也可以修改它然后提交也木有问题(因为其实如果你show in finder会发现其实就在你最开始建的文件夹里面)~

本地库

小优化
  • Q1: 我们如果开发的时候,需要先改podfile把自己要改的模块的库的path指向本地,然后执行pod install,然后修改本地的代码调试并提交测试,测试通过以后,将库推上去,然后打tag,podfile还原用tag来指明库依赖。

A1: 现在我们公司是可以直接add某个库成为dev pod,然后自动就会把podfile里面的依赖改为本地,并把这个库clone到单独的文件夹让我们修改。

  • Q2: 很多依赖的库在github上面,并且引入的库越多,其实编译的代码就越多,github拉取还很慢。

A2: 把三方库都打成静态库,然后放在公司内部仓库,每次install直接从内网拉取静态库文件,这样减少了传输时间也减少了编译时间。

  • Q3: 一份代码,多个target,多个编译schema,但是对应不同的库依赖怎么办呢,比如target A需要某个库但是target B不需要?
answer
  • Q4: 如何把主工程定义的宏同步到pod?

A4: 在install的时候为pod添加宏,也就是hook一下pre_install or post_install

pod添加宏定义

你可能感兴趣的:([iOS] CocoaPods相关)