使用CocoaPods来做iOS项目依赖管理
在我刚开始学习iOS开始时,一些优秀的开源框架的README.md中总有一句pod NAME
。当时不知道这句话是用来做什么的。
在工作之后,往往一个项目会用到多个框架。把它们挨个Add Files
,然后根据框架的README.md
来添加相关的系统依赖和设置正确的编译参数。这样做固然是可以的,但是却平白无故地增加了工作量,而且太容易出错了。
所以,我开始学习使用CocoaPods
来做依赖管理。
文章更新
1月20日:在一些问题的解决方法
中添加问题3;
什么是CocoaPods
CocoaPods是iOS和Mac项目的依赖管理工具。项目所需要的依赖都被写入叫做Podfile
的文件中。CocoaPods会将它们集成到我们的项目中,并且帮我们设置好系统依赖以及编译参数。
安装CocoaPods
CocoaPods是基于Ruby的。OS X是自带Ruby的。所以不需要再次安装Ruby。
$ [sudo] gem install [-n /usr/local/bin] cocoapods
说明:这里的命令格式受Ruby的版本以及OS X版本的影响。如果你的Ruby是2.3.0,那么直接执行gem install就可以了。
如果需要更新CocoaPods,执行$ [sudo] gem install cocoapods --pre
。如果第一次安装使用了sudo
,那么在执行安装操作时需要再次使用sudo,否则会提示Permission denied
。
使用CocoaPods
在使用之前,确保你需要的库在Specs repository或者cocoapods.org上可以查询到。
在新的项目中使用CocoaPods
创建一个新的Xcode项目。
打开终端,执行
$ cd your project direction
,进入到你的项目目录下。$ touch Podfile
,创建一个Podfile文件。打开
Podfile
,在第一行写下platform :ios, '8.0'
,指定平台以及所支持的版本。在单独一行用
pod 'libraryName'
,指定需要导入的依赖。在终端中执行
$ pod install
,就会为项目导入执行的依赖。
CocoaPods提供$ pod init
,可以为我们创建具有模板的Podfile
文件。在$ pod install
执行完成之后,会生成一个projectName.xcworkspace
文件,之后使用这个文件来打开项目。
关于pod install 和 pod update
pod install
第一次为项目添加依赖或者每一次修改Podfile
后使用pod install
。
每次
pod install
被执行,都会下载和安装新的pods。被安装的pods的版本都会写入到Podfile.lock
文件中。这个文件会一直跟踪已安装的每一个pods的版本号,并且锁定这些版本号。当你执行
pod install
,它只会解决那些没有在Podfile.lock
文件中列出来的pods的依赖。对于
Podfile.lock
中列出的pods,只会下载Podfile.lock
明确记录的版本,而不会去查看是否有新的版本。对于没有在
Podfile.lock
中列出的pods,会去匹配Podfile
文件中描述的版本,如pod 'AFNetworking', '~> 3.0'
。
pod update
在执行pod update
之前,可以执行pod outdated
来查看有哪些pods有新的版本。
当你执行pod update PODNAME
时,CocoaPods会尝试发现PODNAME
的可更新的版本,而不会去关注Podfile.lock
中的版本。它会把依赖更新到最新的版本。
当执行pod update
,而不带指定的PODNAME
时,CocoaPods就会将所有列在Podfile
中的依赖更新到最新版本。
当pods被更新时,相应地,Podfile.lock
中的pods的版本号也会更新。
Podfile.lock
这个文件在多人合作同一个项目时可以发挥关键作用。它可以保证每个成员的pods的版本都是统一的。每一次修改Podfile.lock
后,你必须要commit & push它到Repo。
当然,你可以把pod install
之后生成的Pods
文件夹放入到Repo中,来管理依赖版本。
一些问题的解决方法
问题1
在Swift下,配置重写的问题。在执行pod install
时,会遇到下面的提示。
大概的意思就是说,当前的Target想要重写EMBEDDED_CONTENT_CONTAINS_SWIFT
参数。提示下面给出了两个解决方法.
一种是使用$(inherited)
flag。在Target -> Build Settings -> Other Linker Flags下,添加上$(inherited)
。
另一种是移除target -> Build Settings中EMBEDDED_CONTENT_CONTAINS_SWIFT
参数的设置。
出现这个问题的原因是Xcode已有的EMBEDDED_CONTENT_CONTAINS_SWIFT
参数设置和Pods/Targets Support Files/Pods-CocoaPodsDemo
目录下Pods-CocoaPodsDemo.debug.xcconfig
,Pods-CocoaPodsDemo.release.xcconfig
这两个文件中对这个参数的设置不同导致的。所以把这两个参数修改一致,问题就解决了。
对于这个问题,我觉得是CocoaPods在修改我们已经设置过的编译参数之前给出的提示,以防强制修改而带来的无法挽回的损失出现。
问题2
在pod install
时,遇到如下提示。
字面上的意思就是这些依赖没有被任何一个target使用。
这个问题可能出现在使用老版本的podfile文件时出现。现在新的podfile文件都会使用target NAME do
来说明在哪个target中使用依赖。比如这样:
target 'CocoaPodsDemo' do pod 'baiduMap', '~> 2.8' pod 'SwiftyJSON', '~> 2.3' end
只要指定好使用依赖的target,问题就可以解决了。
问题3
在工程编译的时候,提示library not find for -lPods
。
我遇到这个问题的原因是,项目原本的Podfile
没有明确指明target
,所以生成了libPods.a
的静态库文件。
由于某些原因,我重新拉取项目分支,再次使用pod install
,会出现我在问题2
中描述的提示。我用了target
之后,会生成一个libPods-NAME.a
格式的静态库文件,然后会被添加到项目中。
这时,问题出现了,原本的libPods.a
文件并没有从Linker Frameworks and Libraries
编译项中移除,但是我的新分支下的项目中没有这个文件,所以会出现library not find for -lPods
的编译错误。
把libPods.a文件从Linker Frameworks and Libraries
编译项中移除就可以解决问题了。