私有Pods(进阶篇)
私有Pod Spec repo
Spec Repo 是所有Pods的一个索引,就是一个容器,所有公开的Pods都在里面,实际上是Git仓库,remote端在Github上,当你使用了Cocoapods后它会被clone到本地的 ~/.cocoapods/repos目录下,可以进入这个目录下,有一个master文件夹,这个文件夹就是官方的 Spec Repo 了。目录的结构是这样的 . -->Specs-->[SPEC_NAME]-->[VERSION]-->[SPEC_NAME].podspec 因此,如果我们要创建自己的类似于master的私有Spec Repo ,这里我们可以fork官方的Repo,也可以自己创建,个人建议不fork,因为你只是想添加自己的Pods,没有必要把现有的公开的Pods都copy一份,所以创建一个Git仓库,这里我选择Coding,因为Coding可以创建私有库。也可以自己搭建服务器,创建私有库。
在coding上创建自己的spec私有仓库,本地跟踪管理
首先我们在coding上创建一个自己的spec仓库,用来管理自己私有组件的spec文档。
这是我创建好的Pods spec仓库
这是我Coding上私有Pods Spec仓库链接:https://coding.net/u/schiller/p/MyDemoSpec/git
创建完成后在终端执行如下命令
$ pod repo add [Private Repo Name] [Github HTTPS clone URL] 例如我创建的MyDemoSpec: pod repo add MyDemoSpec https://git.coding.net/schiller/MyDemoSpec.git
pod 命令本身在git管理下,所以执行 pod repo add之后就会在cocoapods/repos仓库中新建仓库跟踪远程仓库。如果创建成功的话,进入到 ~/.cocoapods/repos目录下就可以看到MyDemoSpec这个目录了。第一步完成。
注意:如果其他人共同使用这个私有SpecRepo的话在他对应Git仓库的权限的前提下执行相同的命令添加这个Spec Repo 即可。
over.
创建自己的私有组件
通过pod创建自己私有组件库,步骤如下:
首先将组件从项目中拆分出来,组建自己的组件库
然后在终端用 一下命令创建一个pod文件
$ pod lib create PodLibrary
向Pod文件夹中添加库文件和资源,然后配置podspec文件,模块文件放在Pod/Classes中,然后执行 pod update 命令
每次向Pod添加了新的文件或者以后更新了podspec的版本都需要重新执行一遍pod update命令
测试无误后,将项目推送到远程仓库,并编辑podspec
$pod repo push MyDemoSpec PodLibrary.podspec #前面是本地Repo名字,后面是podspec名字
- 编辑podspec,podspec文件的格式和定制如下:
Pod::Spec.new do |s| s.name = "PodLibrary" s.version = "0.1.0" #项目总结 s.summary = "My PodLibrary is a repo for UIButton+Positioning assembly." #项目描述,貌似描述的文字要多于总结的,否则会报警告 s.description = <<-DESC My Private UIButton+Positioning assembly * MarkDown format * It is a nice world! DESC #项目的主页,要求可以访问 s.homepage = "https://git.coding.net" #项目的证书类型,一开始在git 就要配置好 s.license = 'MIT' s.author = { "gaolong" => "gaolong@alibaba.com" } #最重要的一部分,项目的源地址,目前只支持Http\Https, 不支持SSH,小编曾经犯了一个低级错误,将这个source指向了以前建立的一个Spec.git,然后一直报"The `PodLibrary.podspec` specification does not validate"的错误,小编又不会调试,所以很丢人的折腾了两个小时。 s.source = { :git => "https://git.coding.net/schiller/MyDemoSpec.git", :tag => "0.1.0" } s.platform = :ios, '7.0' s.requires_arc = true #表示项目的源文件在Pods/Classes文件夹下 s.source_files = 'Pod/Classes/**/*' s.resource_bundles = { 'PodLibrary' => ['Pod/Assets/*.png'] } #项目的依赖库等等 # s.public_header_files = 'Pod/Classes/**/*.h' # s.frameworks = 'UIKit', 'MapKit' # s.dependency 'AFNetworking', '~> 2.3' end
编辑podspec文件之后,需要验证该文件是否可用,如果有任何WARNING 或者ERROR都是不行的,它就不能被添加到Spec repo ,需要执行以下代码验证
$ pod lib lint
当你看到
-> PodLibrary (0.1.0) PodLibrary passesd validation
说明验证通过了。
- 配置私有组件项目
- 配置.gitignore
每次记住修改完.podspec文件后要上传到本地Specs仓库,pod push,会自动push到远端仓库;要给私有组件项目配置.gitignore,否则私有项目的维护会很困难私有项目gitignore配置如下:
```
- 私有组件项目配置依赖
s.dependency即为私有组件配置依赖,包括第三方依赖库和静态库,静态文件、配置非arc等。其中依赖库的版本如 AFNetworking 的版本要和项目中的项目中的AFNetworking版本兼容,否则会出现版本不一致的报错,无法给项目安装该私有组件库。例如:-`AFNerworking(= 3.0.4)` required by `Podfile`- `AFNerworking(= 3.0.4)` required by `Podfile.lock`- `AFNerworking(~> 2.3)` required by `podTestLibrary(1.0.0)`显然是两个版本不符,pod不知道加载哪一个了。
- over.
- 本地测试PodSpec文件
我们可以创建一个新的项目,这个项目的Podfile 文件直接指定刚才创建好的podspec文件,看是否可用(我这里选Demos ,这个我的测试项目),在Podfile中我们可以这样编辑,有两种方式
platform :ios, '7.0' pod 'PodLibrary', :path => '/Users/schiller/Desktop/PodLibrary/PodLibrary.podspec' #指定podspec 文件 #或者这样 pod 'PodLibrary', :path => '/Users/schiller/Desktop/PodLibrary' #指定路径
然后执行pod install 命令安装第三方库,就像安装AFNetworking那样安装自己的公共组件库,然后发现库文件被加到Pods子项目去了。测试无误后进行下一步,提交podspec到Spec repo中。
- 向Spec Repo提交podspec
回顾一下我们1,2两步所做的工作,接下来我们向我们的私有Spec Repo提交podspec,只需要一个命令,要cd 到私有项目的目录下执行该命令
$pod repo push MyDemoSpec PodLibrary.podspec #前面是本地Repo名字,后面是podspec名字
如果pod repo push 出现报错:
[!]The `PodLibrary.podspec` specification does not validate
多半是你的podspec文件配置不成功。
小编在第三步执行pod lib lint 命令,一直显示该文件pass validate ,但是将 私有项目push 到 本地spec仓库时出现以上报错,于是小编机智地执行一下命令
$pod repo push MyDemoSpec PodLibrary.podspec --allow-warnings
允许报警,然而并没有起到作用
于是小编查看详细日志
$pod repo push MyDemoSpec PodLibrary.podspec --verbose
当小编看到错误原因是自己将s.source源地址写成了之前的源地址的时候,小编内心是崩溃的,QAQ。
通过$ pod lib lint 命令查看私有组件库是否通过验证的问题,
所以首先一定要确定自己的podspec通过验证无误,再一个就是删除无用的注释,尽量规范,完成之后,这个名叫PodLibrary的组建就添加到了我们的私有Spec Repo ,可以进入~/.cocoapods/repos/MyDemoSpec目录下查看
在MyDemoSpec目录下,有PodLibrary文件夹,下面有0.1.0文件夹,PodLibrary.podspec
- 然后我们执行pod search ,就会发现自己的库可以搜到了。
$ pod search podTestLibrary -> podTestLibrary (1.0.0) XTURLRequest Assembly pod 'podTestLibrary', '~> 1.0.0' - Homepage: https://coding.net/u/schiller/p/podTestLibrary - Source: https://git.coding.net/schiller/podTestLibrary.git - Versions: 1.0.0 [GLSpecs repo] - 0.1.0 [master repo]
- over.
使用制作好的Pod
完成一系列操作,就可以使用自己制作好的pod了,回顾一下,就可以弄清楚这个Pod私有库的原理了。
- 私有Pod原理详解
原理: 有一个私有项目(私有组件,PodLibrary),该私有项目的.podspec文件有s.source源指向coding的私有Git仓库;在自己的Cocoapods目录下 , 即~/.cocoapods/repos 仓库下有一个存放私有库链接的Spec(MyDemoSpec,同样要给这个私有的MyDemoSpec建立远端仓库),该spec用来管理私有组件的.podspec,所以私有组件的.podspec文件要push到MyDemoSpec上去; 然后某个项目需要用到私有库,只需要在podfile中加上MyDemoSpec的链接,然后pod update 就实现了将私有组件加载到需要的项目中。每次pod install 时,pod会根据私有spec仓库的.podspec文件找到PodLibrary这个私有组件的链接,然后将PodLibrary私有组件download到项目中,以Pod以来库的形式实现。 同样的道理,之前的公有库的实现方式只是通过~/.cocoapods/repos中的master spec库寻找到需要的存放在Cocoapods上的公有项目,因为master中存放了所有的Cocoapods支持的第三方库的链接,每次pod install ,pod会去master找AFNetworking 的source源链接,该源链接在cocoapods上,然后download下载下来,就在项目中集成了AFNetworking Pods依赖库. 验证:cd 到~/.cocoapods/repos , cd 到master ,cd到Specs,ls -a ,会发现将近6000个公有库,然后cd 到AFNetworking ,ls -a 发现AFNetworking的所有版本,然后cd 到某个版本,发现AFNetworking.podspec.json 文件。就是传说中的.podspec配置文件,然后查看配置,在s.source一栏中发现"git": "https://github.com/AFNetworking/AFNetworking.git",这就是spec保存的AFNetworking 组件的源地址,pod根据spec文件保存的这个地址找到源文件,然后就是pod install 安装AFNetworking 了。
- 我们在项目中可以这样使用自己的私有组件Pod,我们在podfile中这么写,然后再pod install ,就会发现项目中的Pods有PodLibrary这个组件了。
platform :ios, '7.0' inhibit_all_warnings! #公有库 source 'https://github.com/CocoaPods/Specs.git' pod 'MBProgressHUD', '0.9.1' #私有库 source 'https://git.coding.net/schiller/MyDemoSpec.git' pod 'PodLibrary', '~> 0.1.0'
至此,私有pod集成完毕
over.
over.
私有Pod协同合作
- 对于私有pod的协同合作非常简单,Spec仓库放置在~/.cocoapods/repos目录下,自己的Spec仓库放置在coding或者github上,因此只需要执行
$ pod repo add MySpecs https://git.coding.net/schiller/MySpecs.git
~/.cocoapods/repos 就会有这个仓库,该仓库指向我们的私有组件的位置,因此在终端执行
$ pod search podTestLibrary
就能搜索到我们自己的私有组件。只需要在我们的项目中pod install就可以使用该私有组件了。
-
删除私有库
通过如下命令删除
$ pod repo remove MyDemoSpec
over.
部署到公有库
代码创建好了,当然可以提交到公有库了,比如想让大伙都来用自己的组件,这个对个人和团队的影响力是有一定提升的。之前需要审核一两天的时间,现在有了trunk,提价即可使用了。
首先将代码上传到github
注册trunk服务
pod trunk register wskrdfeai@gmail.com 'laughmaker' --description='我爱我的因我觉得欢喜' --verbose
- 可查看注册信息
pod trunk me
- 将仓库上传到公有库中心
pod trunk push MyDmeoSpec
- 也可以将其他人添加进来一起开发
pod trunk add-owner ProjectName(项目名) email(要添加进来的人)
- 至此添加完毕,其他人直接在podfile中就可以搜索和添加你的公有项目了。
提供私有pod测试项目
大家可以通过我已经建立好的项目来调试私有pod,熟悉私有库建立方法,这是小编的项目。(密码可以私戳我)
Specs的仓库: https://git.coding.net/schiller/GLSpecs.git 私有组件仓库: https://git.coding.net/schiller/podTestLibrary.git 测试Cocoapods的demo: https://github.com/schillerGao/MyGLDemos.git
over.
私有组件建立目录层级(配置subspec)
通过上述方式配置的spec文件我们发现,Cocoapods会将所有文件都放在一个文件夹下,并没有建立层级管理,导致主App Pods代码过于冗杂。一个好的方式是使用subspec ,拆分各模块的依赖关系。
Pod::Spec.new do |s| s.name = "XTFoundation" s.version = "0.0.7" s.summary = "小图项目组iOS端基础模块" s.homepage = "https://coding.net/u/xiaotujieshu/p/XTFoundation_iOS" s.license = { :type => "MIT", :file => "LICENSE" } s.author = { "hezhendong" => "wskrdfeai@gmail.com" } s.platform = :ios, "7.0" s.source = { :git => "https://git.coding.net/xiaotujieshu/XTFoundation_iOS.git", :tag => s.version } s.frameworks = "UIKit" s.subspec 'XTNetwork' do |network| network.source_files = 'XTFoundation/XTNetwork/**/*' end s.subspec 'XTMacro' do |macro| macro.source_files = 'XTFoundation/XTMacro/**/*' end s.subspec 'XTHUD' do |hud| hud.source_files = 'XTFoundation/XTHUD/**/*' end s.subspec 'XTRegular' do |regular| regular.source_files = 'XTFoundation/XTRegular/**/*' end s.subspec 'XTSNS' do |sns| sns.source_files = 'XTFoundation/XTSNS/**/*.{h,m}' sns.resources = "XTFoundation/XTSNS/Resources/*.png" sns.dependency 'OpenShare', '~> 0.0.1' end s.subspec 'XTUIUtils' do |uiUtils| uiUtils.source_files = 'XTFoundation/XTUIUtils/**/*.{h,m}' end end
over.
Cocoapods番外篇
Cocoapods制作篇,创建属于自己或者团队的开源项目,供他人使用
可以通过创建自己的依赖库,用来提升个人实力和影响力,或者团队实力和影响力。
使用Cocoapods里没有的第三方库新版本(奇巧淫技)
我们以PlayHavenSDK为例,我们在Cocoapods/Specs这个仓库可以看到,PlayHavenSDK最新版本为1.11.0。而playhaven / sdk-ios里面的tag,已经有了1.12.1这个版本。CocoaPods的Spec repository已经落后了两个版本。这时我们想使用最新版,需要的就是一个更新的spec。
Pod::Spec.new do |s| s.name = 'PlayHavenSDK' s.version = '1.12.1' s.license = 'MIT' s.summary = 'PlayHaven is a real-time mobile game marketing platform to help you take control of the business of your games.' s.homepage = 'http://playhaven.com' s.author = { 'Sam Stewart' => 'sam@playhaven.com' } s.source = { :git => 'https://github.com/playhaven/sdk-ios.git', :tag => '1.12.1' } s.description = "PlayHaven is a real-time mobile game marketing platform to help you take control of the business of your games. Acquire, retain, re-engage, and monetize your players with the help of PlayHaven's powerful marketing platform. Integrate once and embrace the flexibility of the web as you build, schedule, deploy, and analyze your in-game promotions and monetization in real-time through PlayHaven's easy-to-use, web-based dashboard. An API token and secret is required to use this SDK. These tokens uniquely identify your app to PlayHaven and prevent others from making requests to the API on your behalf. To get a token and secret, please visit the PlayHaven developer dashboard at https://dashboard.playhaven.com." s.platform = :ios # PlayHaven includes prefixed versions of SBJson and OpenUDID s.source_files = 'Cache', 'src', 'WaterWorks', 'JSON', 'OpenUDID' s.frameworks = 'SystemConfiguration', 'CFNetwork', 'StoreKit', 'CoreGraphics', 'QuartzCore' s.weak_frameworks = 'AdSupport' end
这里我们注意到s.source这一行配置,指向了playhaven/sdk-ios.git仓库的1.12.1这个tag,表示这个spec将使用这个tag的代码。我们将它保存到本地的一个目录中,如
~/Desktop/PlayHavenSDK/PlayHavenSDK.podspec
。我们回到Xcode project目录中,打开Podfile,添加pod 'PlayHavenSDK', :podspec => '~/Desktop/PlayHavenSDK/PlayHavenSDK.podspec'
,接着运行pod update
即可。PS: 当然这个podspec也可以不放在本地,比如放在gist上。
Cocoapods实战篇记录
在项目切一个cocoapodsDev分支,用来检测使用cocoapods管理第三方库和本地库的一些bug,提前预演,如果能够完全弄好,就迁移到dev分支中。
MyApp当前项目架构
当前项目结构中没有使用Cocoapods管理,使用子模块和framework管理独立业务代码,一方面项目架构不够清晰,另一方面调试相当困难。
迁移测试
首先将baseSDK做成私有Pod、设置好specs文件,然后主App中的删除baseSDK的依赖,然后实现了。pod install主App,于是就集成了Cocoapods。
集成过程中,出现了一个非常诡异的问题,编译通过,但是linker不到Pods集成的库:
linker command failed.
我们查看发现link不到的原因:
- 酒店和金融SDK化,打成了Framework,导致linker不到我们的Pods。
- 第二个原因,在Cocoapods install 第三方库时项目target覆盖了Pods-debug.xcconfig ,导致是没有配置好:http://www.bkjia.com/IOSjc/1017630.html
-
over