CocoaPods私有库的二进制化

前言

假设你已经非常熟练的使用cocoapods来管理私有库,并且实现了组件化的APP设计架构。这篇文章将会帮助你将私有库编译成二进制文件,这样做的好处是会大大缩短编译工程的时间,提升工作的效(bi)率(ge).

目标

我们当前最重要的目标是将私有库编译成二进制文件,但是也有诸多限制条件:

  • 尽量做到不修改原来私有库的所有版本的任何代码
  • 在任何时候都可以随意切换源码和二进制文件,以方便调试
  • 所依赖的第三方库不参与二进制编译

步骤

新建私有Cocoapods库

这里我将新建一个示例的私有库工程,对制作私有Cocoapods库不是非常了解的,可以去先看看其他文章.

$ pod lib create CCDemoLib

按照提示信息依次填写选项,完成之后Xcode会被自动打开到CCDemoLib的pod工程.删除pod目录下的ReplaceMe.m文件.
这里,我将建立两个子库.一个CCUICCNetwork,一个CCDemo.h的头文件.该头文件用来导入所有子库的头文件.CCDemoLib.podspec文件如下:

Pod::Spec.new do |s|
  s.name             = 'CCDemoLib'
  s.version          = '0.1.0'
  s.summary          = '一个测试二进制化的私有库'
  s.description      = '一个测试二进制化的私有库'
  s.homepage         = 'https://github.com/zhahao/CCDemoLib'
  s.license          = { :type => 'MIT', :file => 'LICENSE' }
  s.author           = { 'zhahao' => '506902638@qq.com' }
  s.source           = { :git => 'https://git.coding.net/zhahao/CCDemoLib.git', :tag => s.version.to_s }
  s.ios.deployment_target = '8.0'

  s.source_files = 'CCDemoLib/Classes/CCDemo.h'

  s.subspec 'CCNetwork' do |ss|
     ss.source_files = 'CCDemoLib/Classes/CCNetwork/**/*'
    ss.dependency 'AFNetworking', '~> 2.3'
  end

  s.subspec 'CCUI' do |ss|
    ss.source_files = 'CCDemoLib/Classes/CCUI/**/*'
    ss.dependency 'SDWebImage', '~> 4.1.0'
  end

end

执行pod install,安装完成之后的目录结构是这样的:

目录结构

我们将工程推到远程Git仓库

➜  CCDemoLib git:(master) ✗ git add origin https://git.coding.net/zhahao/CCDemoLib.git
➜  CCDemoLib git:(master) ✗ git add .
➜  CCDemoLib git:(master) ✗ git commit -m 'init project'
➜  CCDemoLib git:(master) git push origin master

发布到私有索引库

添加完tag,推到索引库,这里其实不需要验证的,如果有错误,自然也就推送不进去.等几分钟...

➜  CCDemoLib git:(master) git tag 0.1.0
➜  CCDemoLib git:(master) git push --tags
➜  CCDemoLib git:(master) pod repo push CCPodSpec CCDemoLib.podspec --allow-warnings

然后,成功了~ 到此,我们就发布了一个正常的私有库.

二进制化

前面简单介绍了下私有库的创建,接下来介绍私有库的二进制化方案.

iOS里面的静态库分为.framework和.a两种类型,它们的区别是.framework会包含资源文件,而.a文件是不包含资源文件.一般情况下我们都需要.a类型的静态库,这样每个组件的资源都不会安装到主工程里面去,避免了资源的重复问题,但是主工程里面需要导入需要的所有的图片等资源.

下面以.framework为例子:

生成framework

直接上图:

新建一个framework类型的target,名字是CCDemoBinary
选择framework,如果生成.a选择Static Library
编辑CCDemoBinary的scheme
选择release模式
在Build Settings里面
在Build Settings里面
删除
将下面的直接拖到CCDemoBinary文件夹下
在Build Phases下,将头文件全部拖到public下
选真机的,不要模拟器

修改podfile文件

WX20170930-222316.png

执行 'pod install',等安装完成之后,编译刚才的CCDemoBinarytarget,找到CCDemoBinary.framework,位置如下:

WX20170930-222609.png

右键show in finder 找到CCDemoBinary.framework文件,选Release-iphoneos文件夹里面的那个.

WX20170930-222731.png
在pod文件夹下面

至此,framework已经搞定了,接下来我们要去修改CCDemoLib.podspec文件

修改CCDemoLib.podspec

之前说过,我们需要随时切换源码和二进制文件,所以我们可以利用环境变量来处理这两种情况

$ CCDemoLib_Source=1 pod install

CCDemoLib_Source就是设置了一个环境变量,在.podspec文件中,可以使用ENV['CCDemoLib_Source']来获取

修改之后的CCDemoLib.podspec文件

Pod::Spec.new do |s|
  s.name             = 'CCDemoLib'
  s.version          = '0.1.0'
  s.summary          = '一个测试二进制化的私有库'
  s.description      = '一个测试二进制化的私有库'
  s.homepage         = 'https://github.com/zhahao/CCDemoLib'
  s.license          = { :type => 'MIT', :file => 'LICENSE' }
  s.author           = { 'zhahao' => '506902638@qq.com' }
  s.source           = { :git => 'https://git.coding.net/zhahao/CCDemoLib.git', :tag => s.version.to_s }
  s.ios.deployment_target = '8.0'


if ENV['CCDemoLib_Source'] || ENV['AllLib_Source']
    s.source_files = 'CCDemoLib/Classes/CCDemo.h'
    s.subspec 'CCNetwork' do |ss|
        ss.source_files = 'CCDemoLib/Classes/CCNetwork/**/*'
        ss.dependency 'AFNetworking', '~> 2.3'
    end

    s.subspec 'CCUI' do |ss|
        ss.source_files = 'CCDemoLib/Classes/CCUI/**/*'
        ss.dependency 'SDWebImage', '~> 4.1.0'
    end
else
    s.source_files = 'CCDemoLib/Classes/**/*.h'
    s.vendored_frameworks = 'CCDemoLib/Products/CCDemoBinary.framework'
    s.dependency 'AFNetworking', '~> 2.3'
    s.dependency 'SDWebImage', '~> 4.1.0'
end

end

中间的if...else...end的逻辑中AllLib_Source环境变量的意思是所有私有库判断,CCDemoLib_Source是当前的私有库判断.

当设置环境变量为true,那么,我们这个pod库的source_filesdependency都是引用源码.否则,我们就将source_files全部设置为头文件.并且设置vendored_frameworks为刚才拖进来的framework,第三方库全部为依赖关系,也就是全部为源码.

  • 当我想让所有私有库显示源码,只需要设置AllLib_Source=1
  • 当我们指定某一个私有库为源码,其他都为二进制,只需要设置CCDemoLib_Source=1
  • 当我们想让所有私有库都是二进制,那么就什么环境变量都不设置

测试工程的framework私有库的结构目录如下:

二进制的私有库文件目录结构

可以看到,所有的.m文件全部没有了.
自此,我们就完成了大部分工作.最后就是要将修改后的所有文件提交到Git远程仓库和pod索引库.

提交修改,更新索引库

git提交修改:

➜  CCDemoLib git:(master) ✗ git add .
➜  CCDemoLib git:(master) ✗ git commit -m '二进制化该私有库'
➜  CCDemoLib git:(master) git push origin master

删除之前的tag

➜  CCDemoLib git:(master) git tag
0.1.0
➜  CCDemoLib git:(master) git tag -d 0.1.0
➜  CCDemoLib git:(master) git push origin :0.1.0

设置新的同名tag并提交

➜  CCDemoLib git:(master) git tag 0.1.0
➜  CCDemoLib git:(master) git push --tags

提交新的索引库

➜  CCDemoLib git:(master) pod repo push CCPodSpec CCDemoLib.podspec --allow-warnings

等几分钟成功之后,可以查看一下索引库是否更新了该版本的.podspec文件.

到此为止,我们所有的操作都没有修改源码,也实现了我们之前的三个限制.

清除缓存

由于pod update的原理是先从缓存中读取,即Podfile.lock文件,由于我们没有修改私有库的版本号,所以我们需要先清空缓存,让索引库重新从远程拉取.podspec文件. 所以,当你每次二进制化一个私有库成功之后,都需要清空缓存,不然执行pod install之后都是源码,而不是二进制文件.

➜  CCDemoLib git:(master) pod cache clean --all

使用

在你的APP主工程里面,执行pod install或者pod update:

  • $ CCDemoLib_Source=1 pod update 只安装了CCDemoLib私有库为源码
  • $ pod update 安装了所有私有库为二进制
  • $ AllLib_Source=1 pod update 安装了所有私有库为源码

我们新建了一个测试主工程CocoapodsBinary

platform :ios, '8.0'

use_frameworks!

source 'https://git.coding.net/zhahao/CCPodSpec.git'
source 'https://github.com/CocoaPods/Specs.git'


target 'CocoapodsBinary' do
  pod 'CCDemoLib'
end

执行pod install,完成之后pod目录结构上如下:

目录结构

自此,我们就彻底完成了私有库的二进制!

核心

私有库的二进制化核心就是将原来的私有库编译出一个framework,然后修改.podspec文件,根据不同的环境变量获取不同的对私有库的描述信息,这样通过pod进行安装和更新的时候,安装了不同的文件。

下一期,我将使用fastlane来简化一些流程,避免做一些重复的操作和可能带来的操作失误.

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