CocoaPods 动/静态库混用封装组件化

DingTalk20170818200900.png

动/静态库混用

pods的动静态库混用,相信大多数人一想到就会头皮发麻,体会过的应该都懂,那种无助感。。。。

问题

大型项目里来个尝试性swift过渡,首先就是pod加use_frameworks!来支持pod动态库,接着就是一大片的不支持动态库pod提示error,源码上看不dependency依赖静态库pod其实是不会有问题的,如果你的pod全是源码型也不会有任何问题!

ps:其实我感觉这是bug。。。压根就不是啥问题

正常的pod当静态库用的时候vendored_library,vendored_frameworks两个属性搞定一切。。。

解决

未来

虽说是未来,但我估计也就只有几个月的事吧,CocoaPods马上就要可以加动静态库标签了!长期关注pods源码的估计不以为然,上个月就定下来1.4.0发布,然而现在是1.3.1。。。。。
那老哥们PR了好久https://github.com/CocoaPods/Core/pull/386
看源码写的用法每个pod是可以定义static_framework=true属性,这样其实对简单的小项目半点作用都没有,但大型项目简直是救世的存在!承接上边的问题,对指定pod加静态库标签瞬间解决!

补(已经完美现在1.4.0,唯一要注意的是依赖的其他pod也要保证是静态库或加static_framework为ture,但下个版本就修复不用管了只是还没发布)
Pod::Spec.new do |s|
s.name                  = 'XXXThirdPartSocial'
s.version               = '1.0'
s.summary               = '第三方社交模块'
s.homepage              = 'xxx.xxx.xxx'
s.license               = { :type => 'MIT'}
s.author                = { 'xxx' => 'xxx@163.com' }
s.source                = { :git => 'xxx.xxx.xxx', :tag => "#{s.version}" }
s.platform              = :ios, '7.0'
s.source_files          = ''
s.requires_arc          = true
s.ios.dependency    'UMengUShare/Social/ReducedQQ'
s.ios.dependency    'UMengUShare/Social/ReducedWeChat'
s.ios.dependency    'UMengUShare/Social/ReducedSina'
s.static_framework  =  true
end

现在

接着扯一下现在的解决方案,首先我们针对的就是pod提供framework和.a的情况,核心问题其实是自己怎么建立对framework和.a的支持。
把dependency一些静态库的pod拍平就是现在的解决方法,自己建pod,保证一层支持framework和.a,另外如果实在自己的pod里dependency的静态库pod,这个时候比较好的选择是建立subspec,直接subspec里面封装对静态库的支持。
这里支持的时候要分为3类,先放一个友盟分享的例子:
友盟的framework 和.a都是静态库

Pod::Spec.new do |s|
s.name                  = 'XXXThirdPartSocial'
s.version               = '1.0'
s.summary               = '第三方社交模块'
s.homepage              = 'xxx.xxx.xxx'
s.license               = { :type => 'MIT'}
s.author                = { 'xxx' => 'xxx@163.com' }
s.source                = { :git => 'xxx.xxx.xxx', :tag => "#{s.version}" }
s.platform              = :ios, '7.0'
s.source_files          = ''
s.requires_arc          = true
#s.ios.dependency   'UMengUShare/Social/ReducedQQ'
#s.ios.dependency   'UMengUShare/Social/ReducedWeChat'
#s.ios.dependency   'UMengUShare/Social/ReducedSina'
s.subspec 'XXXThirdPartSocialVendor' do |sss|
sss.source_files            = ''
sss.resource                = 'UMSocialSDK/UMSocialSDKPromptResources.bundle'
sss.ios.vendored_frameworks = 'UMSocialSDK/UMSocialCore.framework','UMSocialSDK/UMSocialNetwork.framework'
sss.ios.vendored_library    = 'SocialLibraries/QQ/libSocialQQ.a','SocialLibraries/Sina/libSocialSina.a','SocialLibraries/WeChat/libSocialWeChat.a'
sss.ios.public_header_files   = 'SocialLibraries/**/*.{h}'
sss.ios.library  = 'sqlite3'
end
end
DingTalk20170817182046.png
动态库Pods封装.a

对.a封装的时候vendored_library属性对应.a,然后看看依赖啥系统库在library,frameworks里加上,最后就是.h,如果你不想暴露的话public_header_files 里加完就不用管了,如果想要暴露给别人调用,只能source_files里再加一遍.h。
上面例子中XXXThirdPartSocialVendor里的source_files为空,但其实.a里的东西你是可以调用的,原因是友盟在他的framework里的头文件引用了.a的头文件,间接让.a的.h公开,这问题在我看来感觉是个bug。。。
所以不想在source_files里再写一遍的也可以建个.h引用一遍所有.a的头文件,最后source_files写你自己的.h,但这只是保证我到处可以通过引用自己的头文件实现方法调用,并不能单个引用对应.a的头文件

动态库Pods封装静态Framework

对静态的Framework封装的时候可以说是最舒服的了,vendored_frameworks加上去基本就万事大吉了,至于依赖啥系统库加library,frameworks这件事,亲测有的时候并不需要!

动态库Pods封装动态Framework

对于动态的Framework封装,我不说估计大家也基本能猜到吧!这就是最难受的,具体情况具体分析,不同情形下用不同套路,就算不用pod也让你很不爽,这里我拿环信客服SDK来讲!

DingTalk20170817183749.png

不用pod你要手动把这SDK拖到上边Embedded Binaries位置头文件才能引用,这个是苹果现在引用动态Framework的套路。。。好烦!
下面讲一下pod怎么搞,如果单纯framework做pod,首先public_header_files要指定xxx.framework/Headers/{.h}不然你头文件找不到,其次source_files里看具体编译情况决定加不加xxx.framework/Headers/{.h},然后就是比较普通的地方vendored_frameworks指定好完事大吉!source_files这个加了的时候还有一个前提就是Framework内引用全是""不能<>,所以大部分情况source_files不加
另一种混合使用感觉这才是最常见的
DingTalk20170818125422.png

这时候不要指定Framework的public_header_files,写一个自己的头文件引用类,把想公开可以调用的在这里#import <xxx.framework/xxx.h>,只能间接把那些搞出去,起作用的只有vendored_frameworks

动态库Pods封装资源文件的调用

高能预警!超级天坑降临!
当你use_frameworks!这么一下你如果自定义的pod有关于resource或resource_bundle的话应该会发现真正的末日降临了,之前的资源全读不出来了!


DingTalk20170818141324.png

一张图片告诉你发生了什么,pod构建动态库的时候你的资源文件都在Framework里!
现在的选择变成:要么资源文件放外面单独加,要么改代码。。。。就问你坑不坑?
放外面单独加我这就不说了太简单,代码写的话其实也要看本身代码的结构什么样,如果像我举例中的SDK基本没救,没有统一的地方获取NSBundle,也没对bundle名称做统一,更没对UIImage设置加扩展!
下面简单说下调用方法

NSString * bundleName=@"Frameworks/xxx.framework/xxx.bundle";

NSString * bundlePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent: bundleName];

NSBundle *bundle= [NSBundle bundleWithPath:bundlePath];

//本地化(拖入.lproj 文件夹即可)
NSString *localizedString=[bundle  localizedStringForKey:@"localizedStringKey" value:@"" table:nil]

//图片获取
NSString *bundleImageName=[bundleName  stringByAppendingString:@"myIcon"];

UIImage *tmpImage=[UIImage imageNamed: bundleImageName];

根据上面代码可以找个单例提供bundleName字段,在模块初始化的时候,先判断xxx.bundle有没有,没有的情况bundleName设置成Frameworks/xxx.framework/xxx.bundle,如果没有bundle而是单纯的资源文件,指定到framework目录里就可以随便用了。

只有这样你的pod才算是支持了CocoaPods 动/静态库,也才算是真正的组件化,而且拆包看.app也会感觉优雅很多,分类明确!

CocoaPods 组件化常识普及

模块开发

在模块开发时可以podfile里指定本地路径,.podspec引入工程内但不要加到target里。这样改podspec方便,而且只是修改文件的话可以随时看到pod的真实效果。
上面说的并不是最好的方式,bug fix可能还不错,真开发一大块没有的东西还是先开发最后写podspec为上策!


DingTalk20170818182404.png
  pod 'xxxModule',:path => '../xxxModule.podspec'

指定Spec Repo

在不指定Spec Repo的情况事实是如下面类似写podfile文件,的确也可以更新,但pod内如果有dependency就不行除非你在外部也pod了你dependency的库。。。如此一来你的podfile就比较臃肿看起来,当然的确是可以凑活用的!

  pod 'xxxxx',:git => 'ssh://git@git.xxxx.cn/xxxxx.git',branch:'master'

其实完全可以在podfile最上面写上

source 'ssh://xxx.com/my/Specs.git'

你只需要把官网的Specs弄下来传到你自己的服务器上,至于怎么上传.podspec文件,可以看下面:

#设置一次我们自己的远程仓库源,类似git remote的概念,REPO_NAME仓库源名,SOURCE_URL仓库源远程地址
pod repo add REPO_NAME SOURCE_URL

#上传.podspec文件到自己的本地命名好的那个仓库源
pod repo push REPO_NAME SPEC_NAME.podspec

不过没事的时候要合并一下https://github.com/CocoaPods/Specs,不然你的外部引用可就跟不上时代的潮流了!

弄懂上面那些基本上已经够做好工程管理的组件化了!

ps:本篇是 IOS组件化与工程管理 的进阶

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

推荐阅读更多精彩内容

  • 静态库与动态库的区别 首先来看什么是库,库(Library)说白了就是一段编译好的二进制代码,加上头文件就可以供别...
    吃瓜群众呀阅读 11,859评论 3 42
  • 原文地址 ,此简书只做备份,强烈推荐原文,毕竟格式比简书好看,还清晰 起因 去年,链家网iOS端,之前由于所有的业...
    南栀倾寒阅读 12,246评论 29 130
  • 介绍 动态库形式:.dylib和.framework 静态库形式:.a和.framework 动态库和静态库的区别...
    齐滇大圣阅读 46,102评论 18 252
  • 项目组件化、平台化是技术公司的共同目标,越来越多的技术公司推崇使用pod管理第三方库以及私有组件,一方面使项目架构...
    swu_luo阅读 21,386评论 0 39
  • 窗外的花,容颜未老。 那是岁月斑驳了最初的模样。 盛开,凋零, 在漫长的岁月里, 等待着属于刹那间的绽放。 身以...
    念吻阅读 286评论 0 0