Xcode项目引入Cocoapods管理(基础篇)

项目组件化、平台化是技术公司的共同目标,越来越多的技术公司推崇使用pod管理第三方库以及私有组件,一方面使项目架构更加清晰,一方面现有的工具Cocoapods提供了近乎完美的解决方案。这里我们来讨论一下如何在Xcode 工程中集成Cocoapods,这里提供入门级别的集成和进阶集成方式。

本文目录

参考文档汇总

  1. Cocoapods官网:https://cocoapods.org/
  2. Cocoapods在github上的开发仓库:https://github.com/CocoaPods/CocoaPods
  3. Cocoapods 错误汇总 https://github.com/CocoaPods/CocoaPods/issues
  4. Cocoapods帮助界面http://guides.cocoapods.org/using/using-cocoapods.html
  5. Cocoapods入门参考文档:http://www.tuicool.com/articles/RzI3ye
  6. 创建私有pod参考文档: http://www.cocoachina.com/ios/20150228/11206.html
  7. 私有Pods: http://blog.wtlucky.com/blog/2015/02/26/create-private-podspec/
  8. 淘宝技术架构:http://blog.cnbluebox.com/blog/2014/03/31/cocoapodsdai-ma-guan-li/

项目中配置Cocoapods解决方案

Cocoapods简介

Cocoapods是OS X和iOS下的一个第三方库管理工具,并且支持Objective-C和swifit语言。通过Cocoapods为项目添加称为"Pods"的依赖库(这些库必须是Cocoapods所支持的),并且轻松实现第三方库的版本管理。

引入Cocoapods的意义:

Cocoapods在引入第三方库时自动为我们完成各种配置,包括配置编译阶段、连接器选项、甚至是ARC环境下的-fno-objc-arc配置等

Cocoapods可以很方便的查找第三方库,可以快速方便的寻找到优秀的第三方库以及它们的各种信息。

Cocoapods 官方网站:

https://cocoapods.org/

Cocoapods整个项目托管在github上, 所有的Pods依赖库也都依赖github

https://github.com/CocoaPods

Cocoapods发展背景

Cocoapods创建于2011年,目前Cocoapods团队有17位核心开发人员以及多达5000多个开源项目。Cocoapods的存在为代码分发提供了非常便捷的解决方案。

Cocoapods核心组件

Cocoapods是用Ruby写的,所以在安装时有时要更新ruby源。Cocoapods在解析过程中最重要的几个包的路径分别是:CocoaPods/CocoaPods、 CocoaPods/Core和 CocoaPods/Xcodeproj,其中Core提供了CocoaPods相关文件,主要是podfile和podspecs。

podfile:该文件用于配置项目所需的第三方库,可以被高度订制。

podspec:该文件描述一个库如何被加入到工程文件中。.podspec文件可以标识该第三方库所需要的源码文件、依赖库、编译选项,以及其他的第三方库所需的配置。

over.

Cocoapods与项目sdk化

有些项目处于某些模块采取的是将该业务代码打成framework,如比较重要的金融支付模块。我们在集成私有Pod过程中,将AFNetworking这种第三方库用用Cocoapods管理,其实是打成了.a,而金融sdk仍然使用framework,打成.framework,因此二者无法链接,在Link阶段报错。解决方案是,要么将金融打成.a,要么在金融打成sdk时不勾选AFNetworking

gitmodule的关系与解决方案

子模块和Cocoapods都是试图解决同样的问题。使用子模块的业务准备迁移到Cocoapods 首先需要解耦,模块间解耦。

安装和使用Cocoapods

CocoaPods安装步骤
  • 升级Ruby环境,更新gem 源**
    终端输入:
$sudo gem update --system

ps:国内需要切换源

  • 安装CocoaPods要访问cocoapods.org,该网站已经被天朝墙壁,需要更换镜像来安装(淘宝镜像已经停止更新)
1、gem sources --removehttps://rubygems.org/
2、gem sources -a https://gems.ruby-china.org/
3、gem sources -l 
  • 安装Cocoapods
sudo gem install cocoapods
  • 启动Pod
$pod setup
Pod 常用命令

Pod创建Podfile文件有一下几个步骤:

  • pod 常用命令
搜索类库
pod search AFNetworking
更新第三方库: pod update导入第三方库:
pod install 可以删除podfile中某个库的代码,然后: pod install 
删除第三方库 :pod uninstall 
查看Cocoapods版本: pod --version
查找第三方库: pod search AFNetworking
  • $ cd 到工程文件目录,然后创建Podfile文件
$ touch Podfile(创建Podfile文件)
  • $ vim Podfile编辑该文件,然后通过wq保存(具体可参考vim命令行)
platform :ios, '7.0'
inhibit_all_warnings!
pod 'SDWebImage', '3.7.3'
pod 'SSZipArchive', '1.0.1'
pod 'JSPatch', '0.1.5'
pod 'TMCache', '2.1.0'
pod 'FLEX', '2.2.0'

配置成功后执行命令

$ pod install
  • 项目新增四个文件, Podfile、Podfile.lock、.xcworkspace、podfilelock.manifest以后就可以使用Pod来管理自己的组件库,
  • 以后打开后缀名为 .xcworkspace文件打开工程
pod语义化版本规范
pod 'AFNetworking'  // 不显式指定依赖库版本,表示每次都获取最新的版本
pod 'AFNetworking', '2.0'  //只使用2.0版本
pod 'AFNetworking', '> 2.0'     //使用高于2.0的版本  
pod 'AFNetworking', '>= 2.0'     //使用大于或等于2.0的版本  
pod 'AFNetworking', '< 2.0'     //使用小于2.0的版本  
pod 'AFNetworking', '<= 2.0'     //使用小于或等于2.0的版本  
pod 'AFNetworking', '~> 0.1.2'     //使用大于等于0.1.2但小于0.2的版本  
pod 'AFNetworking', '~>0.1'     //使用大于等于0.1但小于1.0的版本 
pod 'AFNetworking', '~>0'     //高于0的版本,写这个限制和什么都不写是一个效果,都表示使用最新版本

over.

Podfile与多target

Podfile本质上是用来描述Xcode工程中的targets用的。如果我们不显式指定Podfile对应的target,Cocoapods会创建一个名为default的隐式target,会和我们工程中的第一个target对应。换句话说,如果在Podfile中没有指定target,那么只有工程中的第一个target能够使用Podfile中的描述的Pods依赖库。根据需要,给不同的target指定Pods依赖库。

  • 例如,名称为MyApp的target和MyPro app的target都需要Reachabilitiy、SBJson、AFNetworking三个Pods依赖库,可以使用link_with关键字来实现,将Podfile写成如下形式:
link_with 'MyApp', 'MyApp pro'
platform :ios 
pod 'Reachability', '~> 3.0.0'
pod 'SBJson', '~> 2.6.0'

platform :ios , '7.0'
pod 'AFNetworking'
  • 不同的target使用完全不同的Pods依赖库

CocoaPodsTest这个target使用的是Reachability、SBJson、AFNetworking三个依赖库,但Second这个target只需要使用OpenUDID这一个依赖库,这时可以使用target关键字,Podfile的描述方式如下:

target :'MyApp' do  
platform :ios    
pod 'Reachability',  '~> 3.0.0'    
pod 'SBJson', '~> 4.0.0'    

platform :ios, '7.0'    
pod 'AFNetworking', '~> 2.0'  
end  

target :'MyApp pro' do  
pod 'OpenUDID', '~> 1.0.0'  
end  
  • over
主App link Pods库

在集成Cocoapods后,主App可以编译通过,但是无法link到Pods 库的情况。首先,我们看一下主App是如何引入Pods中的项目,编译没有问题,关键在于link。

Cocoapods与持续集成

集成Cocoapods后对项目的持续集成的影响。项目采用OClint进行持续集成,集成Cocoapods之后,该将哪些文件加入到持续集成中。

Cocoapods与项目SDK化

MyApp项目中集成了Cocoapods,使用Cocoapods管理第三方库公共库,类似AFNetworking、MJExtension等,同时使用私有Pod管理MyFoundation等私有组件。并且建立私有Pod管理单品类业务。因此主App中Pods分为三部分:

  • 开源第三方库
  • MyApp私有组件库(Foundation、Catogery等)
  • 单品类业务(MyApp主要涉及酒店模块、机票模块等)

对于这几部分,Cocoapods会将Pods打成libPods.a,独立模块供主App使用。

遇到的一个问题是,因为项目中存在金融模块的SDK(部分模块已经SDK化),而金融业务代码用到了AFNetworking,金融业务代码使用AFNetworking的方式是,主App给金融SDK一个AFNetworking的framework,金融使用该framework后可以调试相关代码,但是在金融打成framework给主App时不勾选AFNetworking这个target。因此具体的是:

金融SDK -->link --> 主App AFNetworking(AFN手动导入主App).

到目前为止,没有导致任务问题。

然后如果集成Cocoapods后,AFNetworking放在Pods中管理,而Pods被Cocoapods打成了podlib.a,.a与.framework的访问就会出问题, .framework无法link到.a里的AFNetworking,最终导致link错误。对于这个问题,估计有多种可行的方案:

  1. 方案一:给金融模块提供 AFNetworking.a 而不是 AFNetworking.framework。
  2. 方案二:金融模块打framework时剔除AFNetworking ,在其打成framework时不勾选 AFN相关文件。(这种方式通过检验,因为金融模块不需要 link AFNetworking.framework)。
  3. 方案三:暂未定

over。

Cocoapods与App打包

目前我们App提供三种打包方式,第一是Xcode打包,第二是ipa_genator.sh脚本打包,第三是测试用jenkins打包。集成Cocoapods后,这三种打包方式相关配置需要更改,否则不支持打包或者打包失败。

  • Xcode打包,只需要使用MyApp.xcworkspace来编译运行程序,就可以打包成功。
  • 脚本打包,需要更改相关配置,更改如下:
#config.cfg文件为脚本打包路径配置文件,之前的路径指向的是MyApp.xcodeproj,我们需要将PROJECT_NAME改为:
PROJECT_NAME="MyApp.xcworkspace"
#因为每次打包需要首先build,而项目集成Cocoapods后,build路径是xcworkspace而不是原来的xcodeproj,因此需要指定正确的路径。
#其次,我们需要将ipa_generator.sh文件中的

PROJ_EXT=".xcodeproj" #此处改为 PROJ_EXT=".xcworkspace" 

xctool_archive()
{
xctool -project $1 \  # 此处改为xctool -workspace
-scheme $2 \
-reporter json-compilation-database:compile_commands.json \
-sdk iphoneos \
archive \
-archivePath $3
}

xcodebuild_archive()
{
xcodebuild -project $1 \ # 此处改为xctool -workspace
-scheme $2 \
-sdk iphoneos \
archive \
-archivePath $3 \
| tee xcodebuild.log
}

over.

  • jenkins打包失败的问题。
Cocopods集成时间表
  1. 将原来的手动添加的第三方库迁移到现在的Cocoapods管理第三方库,需要将原来第三方库的配置相关的文件删除干净。Cocoapods会将第三方库的所有需要配置的静态库或者文件集成在libPods.a静态库中,在Build Phases中可以找到这个.a静态库。鉴于这个考虑,我们需要删除原来手动添加的第三方库的配置文件。

  2. 纪录所有的原来的第三方库的配置文件,一并删除

  • AFNetworking
  • FLEX
  • FMDB
  • ...
Cocoapods常见问题汇总
  1. Pods依赖库已经更新

  2. Cocoapods无法安装的问题。

Mac系统升级到10.11使用Cocoapods出现pod:command not found 解决方案

$ sudo gem install -n /usr/local/bin cocoapods

如果podupdate 或者pod install 还卡在哪儿,则

  1. pod install 或者pod update 速度慢的问题
查看ruby源,更换为淘宝镜像,如果还出现问题,则
原因可能是:当执行以上两个命令时会升级Cocoapods的Specs仓库,加一个参数就可以省略这一步,然后速度可能会提升。参数命令如下:
pod install --verbose --no-repo-update
pod update --verbose --no-repo-update 
执行完命令以后有时还是会报错,不妨更新一下本地repo
pod repo update 
  1. 这个问题是比较常见的问题
"podfile.lock" not such file or directory......

http://stackoverflow.com/questions/17072396/cocoapods-errors-on-project-build

  1. 集成Cocoapods编译通过但是链接不通过的问题。
Undefined symbols for architecture x86_64:

"_OBJC_CLASS_$_AFNetworking", referenced from:

objc-class-ref in HJCXMPPTools.o

ld: symbol(s) not found for architecture x86_64

clang: error: linker command failed with exit code 1 (use -v to see invocation)

小编发现,小编之前是手动导入的AFNetworking这个第三方库,小编估计是手动导入时更改了某些配置文件导致与Cocoapods集成时的配置文件发生冲突,导致无法link。于是小编在此用Cocoapods更新框架时,发现终端的一段警告:

[!] The `myQQ [Debug]` target overrides the `OTHER_LDFLAGS` build setting defined in `Pods/Target Support Files/Pods/Pods.debug.xcconfig'. This can lead to problems with the CocoaPods installation

- Use the `$(inherited)` flag, or

- Remove the build settings from the target.

这下的思路应该是,手动导入AFN时修改了某些配置,修改了Other Linker Flags。

所以解决方案是:

按照提示,在Build setting里的Other Linker Flags增加$(inherited)。喜大普奔,这个错误算是解决了。

over.

  1. 需要加入gitignore的文件:

  2. 对MyApp包大小的影响、对编译时间和编译速度的影响

  3. 如何更新第三方库

  4. 第三方库与项目代码中的文件重名冲突

  5. 第三方库的sdk版本与项目sdk版本不符时解决方案

  6. Cocoapods软件版本更新

  7. Cocoapods 目前版本为 0.39.0, 最新的1.0.0为测试版

  8. 当两个库同时需要使用AFNetworking时,Cocoapods会确定一个同时能被这两个库使用的版本,然后将同一个安装版本链接到两个不同的库中。

  9. 安装pod install 第三方库过程中,Cocoapods会使用递归来分析所有的需求,并且建立一个代码相关性的图,最后将Podfile序列化为Podfile.lock

  10. 选择的文件夹对:

Could not automatically select an Xcode project. Specify one in your Podfile like so: xcodeproj 'path/to/Project.xcodeproj'

问题出在你选择的项目文件夹不对,应该选择Iphone文件夹集成Cocoapods

  1. 如果项目中有与Pod同名的文件。编译不会通过。

  2. 对于那些不在Cocoapods公共Git仓库中的库,可以用任何一个Git,Mercurial或者是SVN仓库取代,并且还可以指定具体的commit,branch或者tag。 即私有pod。

pod 'Y', :git => 'https://github.com/NSHipster/Y.git', :commit => 'b4dc0ffee' 
  1. over.
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容