之前整理过一种打包静态库的方法: 打包静态库(源码中包含其他静态库以及开源库)。不过这种方式的缺点很明显:1. 需要自己使用Xcode创建静态库工程;2. 需要手动处理代码中依赖的第三方开源库;3. 如果静态库工程依赖私有库,当这些私有库有更新时,就得把他们重新拷贝一份到静态库工程,不够灵活。
因为公司需要持续性向别人提供一套即时通讯SDK,按照之前的方式打包静态库真是太痛苦,SDK依赖的一些私有库会有频繁的更新,依赖的第三方库也是错综复杂。我迫切需要找到一种更方便的打包静态库的方式,既能随时更新私有库,也能解决开源库的冲突问题(比如你的SDK包含了AFNetworking
,别人项目中本身也含有AFNetworking
,就会产生冲),那就是使用cocoapods。
假设你已经有一堆写好的源码,并且它们依赖一堆私有库和第三方库,也许,这些依赖并非都是源码,可能也包含了静态库(.a
或者.framework
)。没关系,先放在那吧。
1. 创建你的 project
打开终端,cd 到你喜欢的某个文件路径,输入 pod lib create YOUR_POD_LIBARY_NAME
创建并初始化一个工程。
然后回答几个问题,就自动创建出一个project:
问题选项
我们新建的工程以及目录如下:
YJDemoSDK project其中重要文件夹我都已经展开,可以看到里面包含的内容,其他没有展开的文件夹不用管它。
从上向下看,最重要的一个就是YJDemoSDK.podspec
文件,*.podspec
是关于pod库的描述文件,它详细说明了在这个pod library
中源码应该从哪里取出、应用怎样的构建设置以及其他基本的信息,比如名称、版本、描述等。下面插播一段关于.podspec
文件的植入性广告:
podspec文件的内容如下所示,每一项是什么意思都做了简要解释,不明白可以去看官方文档:
Pod::Spec.new do |s|
s.name = 'YJDemoSDK' #项目名
s.version = '0.1.0' #相应的版本号
s.summary = 'A short description of YJDemoSDK.' #简述
s.description = <<‐ DESC #详细描述
TODO: Add long description of the pod here.
DESC
s.homepage = 'https://github.com/yangjie2/YJDemoSDK' #项目主页
s.license = { :type => 'MIT', :file => 'LICENSE' } #开源协议
s.author = { 'yangjie2' => 'yangjie2@guahao.com' } #作者
s.platform = :ios, '8.0' #支持的平台
s.requires_arc = true #arc和mrc选项
s.libraries = 'z', 'sqlite3' #表示依赖的系统类库,比如libz.dylib等
s.frameworks = 'UIKit','AVFoundation' #表示依赖系统的框架
s.ios.vendored_frameworks = 'YJKit/YJKit.framework' # 依赖的第三方/自己的framework
s.vendored_libraries = 'Library/Classes/libWeChatSDK.a' #表示依赖第三方/自己的静态库(比如libWeChatSDK.a)
#依赖的第三方的或者自己的静态库文件必须以lib为前缀进行命名,否则会出现找不到的情况,这一点非常重要
#平台信息
s.platform = :ios, '7.0'
s.ios.deployment_target = '7.0'
#文件配置项
s.source = { :git => 'https://github.com/yangjie2/YJDemoSDK.git', :tag => s.version.to_s }
#配置项目的目标路径,如果不是本地开发,pod init/update会从这个路去拉去代码
s.source_files = 'YJDemoSDK/Classes/**/*.{h,m}' #你的源码位置
s.resources = ['YJDemoSDK/Assets/*.png'] #资源,比如图片,音频文件等
s.public_header_files = 'YJDemoSDK/Classes/YJDemoSDK.h' #需要对外开放的头文件
#依赖的项目内容 可以多个
s.dependency 'YYModel'
s.dependency 'AFNetworking' '2.3'
明白了.podspec
文件是什么之后,继续往下看我们的工程目录,有个文件夹 Development Pods ,这里就是放置我们的源码和图片等资源文件的地方,要与YJDemoSDK.podspec
文件中描述的一致。当你向YOUR_POD_LIBARY_NAME/Classes
、YOUR_POD_LIBARY_NAME/Assets
添加新的/已经存在的文件,或者更新你的.podspec
时,需要运行pod install
或者pod update
。
Development Pods
Development Pods are different from normal CocoaPods in that they are symlinked files, so making edits to them will change the original files, so you can work on your library from inside Xcode. Your demo & tests will need to include references to headers using the#import <MyLib/XYZ.h> format.
Note: Due to a Development Pods implementation detail, when you add new/existing files to Pod/Classes or Pod/Assets or update your podspec, you should run pod install or pod update.
2. 配置podspec文件,添加自己的代码
上面创建了一个pod library项目YJDemoSDK
,可以看到项目的文件目录结构,并对几个重要的地方进行了单独说明。下面就开始设置它。
向Classes中添加源码替换掉ReplaceMe.m
文件(为了简单,这里添加YJDemoSDK.h
和 YJDemoSDK.m
)。YJDemoSDK.podspec
文件配置结果如下图:
配置完之后,切到终端,使用 pod lib lint ***.podspec
验证是否有效,必须没有错误,没有警告才可以通过验证。
由于YJDemoSDK依赖私有库YJHelloDog
,并且这个私有库中包含静态库(.a)文件,所以在验证时,需要键入如下命令:
pod lib lint --sources=git@git.guahao-inc.com:yangjie2/snowRepo.git,https://github.com/CocoaPods/Specs.git --use-libraries --allow-warnings
其中,--sources=git@git.guahao-inc.com:yangjie2/snowRepo.git,https://github.com/CocoaPods/Specs.git
指定了我们的私有Repo地址和cocoapods官方的Repo,并且是master分支。--use-libraries
表示依赖了静态库,--allow-warnings
忽略警告。这样就可以验证通过了。
然后cd到YJDemoSDK的Example目录,执行
pod install。
幽怨的发现,出错了,找不到YJDemoSDK依赖的YJHelloDog这个仓库。
找不到YJDemoSDK依赖的YJHelloDog这个仓库不过问题也很显然, YJHelloDog 是私有库。在podfile文件中,添加上我自己的Repo 地址就好。
podfile文件再次执行 pod install,就没问题了。
执行 pod install
这时候再看下pod项目的目录,发现已经添加好了源码和依赖库:
YJDemoSDK 目录3. 提交,打tag
YJDemoSDK 项目配置完成,添加了自己的源码,也添加了依赖的私有库、第三方开源库。提交所有的更新,打tag,push到托管服务器(比如gitHub等)。
打开终端,重新 cd 到 YJDemoSDK 路径,执行以下命令进行提交、打tag,推送tag到远端托管服务器。
git add .
git tag -a 0.1.0 -m 'version 0.1.0'
git push origin 0.1.0
4. 打包静态库
前面的准备工作完成,最后一步就是打包静态库了。这里需要安装一个 CocoaPods 打包插件 cocoapods-packager
。终端执行安装命令:sudo gem install cocoapods-packager
,等待安装完成。
该插件通过对引用的三方库进行重命名很好的解决了类库命名冲突的问题。
终端cd到项目所在目录下,执行以下命令即开始打包静态库:
pod package YJDemoSDK.podspec --library --force --no-mangle --spec-sources=http://git.guahao-inc.com/yangjie2/snowRepo.git,https://github.com/CocoaPods/Specs.git
# --library 表示打包成.a文件。--force 表示强制覆盖之前存在的文件
pod package YJDemoSDK.podspec --force --no-mangle --spec-sources=http://git.guahao-inc.com/yangjie2/snowRepo.git,https://github.com/CocoaPods/Specs.git
# 没有--library,则打包成.framework文件
上面的命令中,有一个是--no-mangle
,表示Do not mangle symbols of depedendant Pods
,当你的项目依赖包含静态库时,不加上这句,就会打包失败:
到此为止,.a 形式的静态库打包成功!刚才打包好的静态库就在我的项目路径下YJDemoSDK-0.1.0文件夹中,里面的文件如下图所示:
静态库目录蓦然发现,没有头文件。。。我希望公开被
别人调用的头文件跑哪里去了?这样打出来静态库也没办法用。google了下,找到一种不是答案的答案,这是cocoapods package 的一个bug,不知道为啥没被修复。或者哪位老铁有了解决方法还请不吝分享下。
这样只能打包成framework了,它是有头文件的。目录如下图:
framework静态库使用时,直接拖到项目中,然后 #import <YJDemoSDK/YJDemoSDK.h>
,使用#import "YJDemoSDK/YJDemoSDK.h"
形式是找不到文件的,要使用尖括号。拖到你的项目中,编译时会出错:
原因是找不到
YJHelloDog.a
文件,这个文件是我们的静态库依赖的另一个静态库,它是不会被打包进framework的,需要你手动添加进项目,所以再把依赖的这个静态库 YJHelloDog.a
拖进项目就好了,运行成功,显示toast提示:hello dog. 说明方法调用成功。至此才算结束了。
使用这种方式打包静态库,在私有库或者开源库有更新时,只需 pod update ,再次执行打包命令就好了,是不是很方便?
网友评论
提示colorFromHex 方法找不到 但是我又在pch 里面引用了 很难受哇
我做了一个最简单的测试,没有依赖任何第三方库,只是打印,用packger打包出来的framework
好比我的framework叫做xxx.framework
我导入使用的时候 我期待的效果是#import <xxx/xxx,h>
但是#import <xxx.framework/下面居然还要Header
最后只能出现是#import "xxx.framework/Headers/xxx.h"我真的很崩溃啊
设置BuildSetting中的 Header Search Paths ,新增 "$(PROJECT_DIR)/Frameworks/***.framework/Headers" ,指明头文件路径。