我报名参加金石计划1期应战——瓜分10万奖池,这是我的第1篇文章,点击检查活动详情
前语 项目布景
项目里边有这么一个需求,在一个App项目中创立多个Static Library,各司其职进行模块与责任划分。
别问为啥没有使用私有库Cocopods进行,横竖现在便是为了便利后续各个Static Library,能够随便拖动到其他项目中进行复用。
然后,问题来了。
问题:在Static Library无法引证友盟的framework
为了便于阐明与演示,我特别创立了一个Demo,经过截图进行讲解。
我有个项目叫做TestUM,里边包括一个SomeSDK,我期望在SomeSDK里边,包括高德地图和友盟统计的功能。
于是乎,我在Podfile文件中进行了装备:
target 'SomeSDK' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!
pod 'AMapSearch', '= 8.1.0'
pod 'AMapLocation', '= 2.8.0'
pod 'UMCommon', '~> 1.3.4.P'
pod 'UMSPM'
pod 'UMCCommonLog'
end
target 'TestUM' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!
# Pods for TestUM
end
注意,进行Pod的target是SomeSDK
而非TestUM
,可是实际上TestUM
也是能引证高德与友盟的库。
最后,依据友盟集成的文件,需求增加桥接文件进行处理:
在TestUM下,我经过import AMapFoundationKit
,咱们能够顺畅的调用高德的相关API,由于桥接了友盟,我也能够顺畅的调用友盟的相关API:
然而,在SomeSDK下,由于能够import AMapFoundationKit
,我依旧能够调用高德,可是友盟却怎么也点不出来了:
我测验在SomeSDK也创立一个相似主工程中Bridging-Header.h
的文件,对友盟进行桥接,然而得到的却是编译错误using bridging headers with framework targets is unsupported
。
不支持,这条路被堵死了。
假如桥接行不通,SomeSDK就无法使用友盟统计的功能,只能将其相关业务移植到主工程去,这显着不符合公司要求。
领导就一句话:高德能够,友盟为什么不行?
现在回头看看,为何高德地图的既能够在TestUM又能够在SomeSDK中进行引证——由于它能在工程中的*.swift
文件中进行import
。
而友盟在经过TestUM-Bridging-Header.h
文件进行桥接后,在TestUM
主工程的.swift
文件中,无需import,直接调用即可,可是在SomeSDK
的子工程中无法调用。
高德与友盟的架包到底有何差异?
AMapFoundationKit.framework与UMCommon.framework比照
其实高德与友盟的Pod引证还是非常相似的,由于都是封装的静态库,Pod集成的都是非开源的.framework架包。
这里咱们将AMapFoundationKit.framework与UMCommon.framework做一下比照:
高德 | 友盟 |
---|---|
- 经过Xcode展开工程看,Pod中,
AMapFoundationKit.framework
不仅展现了Frameworks文件夹,一起露出的.h文件也显现了,而UMCommon.framework
没有显现.h文件。 - 经过
AMapFoundationKit.podspec.json
与UMCommon.podspec.json
,咱们会发现尽管两者都是.framework
的pod集成方法,可是在装备参数的差异方法决定了显现不同。 - 看.framework的文件结构,很显着的发现
AMapFoundationKit.framework
比UMCommon.framework
多一个Module文件夹!
就让咱们看看,这个Module文件夹下面吧。
里边就只有一个module.modulemap
文件,里边长这样:
关于umbrella header
我们能够看看参考文档What is an umbrella header?,它的功能便是将AMapFoundationKit.h
里边露出的.h
文件,经过循环都露出出来。
AMapFoundationKit.h
里边长这样:
回想一下,咱们能够在*.swift
文件中能够import AMapFoundationKit
是不是由于有module.modulemap
中的装备原因?
带着这个问题,我去搜索了一下module.modulemap
的相关资料。
在一篇文章中我找到相关的信息与灵感:
AsBridging-Headercan help us inApp TargetandApp Test Target,not in static library or dynamic librariesto use the Objective C / C APIs into Swift classes,modulemapcan help us here.
经过理解,Pod这种.framework
的静态库,在主工程的使用能够经过桥接处理,而在主工程的的static library则需求经过modulemap来进行处理。
为UMCommon.framework手搓一个module.modulemap
本着死马当活马医的想法,我想为UMCommon.framework手搓一个module.modulemap
。
首先我特别看了一下UMCommon.framework中Headers里边的文件:
抱着试一试的态度,我新建了Modules一个文件夹,并写了这样一个文件,注意我并没增加所有的.h文件,仅仅为了便利测验。
framework module UMCommon {
header "MobClick.h"
header "UMConfigure.h"
header "UMCommon.h"
export *
}
然后将其放到对应的UMCommon.framework。
见证结果的时刻来了,编译,试着import,成功了!
咱们乃至能够,点击看看这个import UMCommon
。
MobClick
类现已完美经过Swift表示了。
而且此时,咱们能够把主工程里边的Bridging-Header.h
里边桥接文件注释掉(乃至将这个.h
文件删除),在*.swift
中import
对应的类,即可成功引入与调用!
总结
-
将Pod中的某些需求桥接的库,经过手搓一个
module.modulemap
,咱们彻底有能力抹去桥接操作,可是一起这样有一个问题,一旦Pod的库,晋级或许文件进行了改变,自行写的module.modulemap
或许也需求更改。而且更改Pod下的库的文件,也不太符合操作规矩。
另外,我们能够测验把
AlipaySDK.framework
经过这种方法去除桥接试试,原理都是一样的,就当练手。 -
还有一种方法便是自己创立一个私有的Spec,自己增加
module.modulemap
后,进行pod库办理,可是这样还是避免不了上游更新,私有库也要同步更新的问题。
最好的Pod集成方法,就像高德的库,官方将podspec
装备好,使用者直接傻瓜pod install
就好了。
参考文档
What is an umbrella header?
Swift Objective C interoperability, Static Libraries, Modulemap etc…
自己写的项目,欢迎我们star⭐️
RxStudy:RxSwift/RxCocoa框架,MVVM形式编写wanandroid客户端。
GetXStudy:使用GetX,重构了Flutter wanandroid客户端。