隨著動態(tài)庫的流行鞭铆,靜態(tài)庫越來越少了(關(guān)于動態(tài)庫和靜態(tài)庫的介紹請點(diǎn)擊)矛市,但是不排除項(xiàng)目中有些依賴的第三方還是使用的靜態(tài)庫。那么這種情況下就可以考慮优俘,將第三方靜態(tài)庫做一個二次封裝京办。一來和業(yè)務(wù)代碼進(jìn)行隔離,方便以后第三方庫的升級帆焕,二來將靜態(tài)庫封裝進(jìn)動態(tài)庫里便于管理和利用動態(tài)庫的優(yōu)勢臂港。一般情況下,用動態(tài)庫封裝靜態(tài)庫很簡單视搏,就是將靜態(tài)庫直接拖進(jìn)動態(tài)庫的工程里审孽,直接編譯即可。但是有一種情況下這么做是不行的浑娜,需要暴露靜態(tài)庫的頭文件佑力,也就是雖然靜態(tài)庫放在動態(tài)庫里面了,但是靜態(tài)庫的頭文件還要提供給上層應(yīng)用調(diào)用筋遭。
下面以封裝百度地圖為例打颤,介紹如何將第三方靜態(tài)庫封裝進(jìn)動態(tài)庫。
百度地圖根據(jù)業(yè)務(wù)不同漓滔,劃分了很多不同的包编饺,大概包括基礎(chǔ)包、定位包响驴、地圖包透且、搜索包、工具包、全景包等秽誊。如下圖所示:
首先锅论,新建一個動態(tài)庫工程讼溺,直接將這些包拖入到工程中。
第一種束析,用代碼將百度地圖庫封裝一層。
也就是自己代碼調(diào)用百度地圖庫憎亚,然后將自己代碼對外暴露员寇,供應(yīng)用層調(diào)用。這是最好的一種思路第美,不僅能解決問題蝶锋,還能將第三方庫和自己的項(xiàng)目業(yè)務(wù)隔離去耦合。對于一般的庫(比較小的庫)什往,非常推薦這種思路扳缕。但是對于百度地圖來說,不好執(zhí)行别威,因?yàn)榘俣鹊貓D的API太多太復(fù)雜了躯舔,如果一點(diǎn)一點(diǎn)去封裝,工作量太大了省古。當(dāng)然有人說粥庄,不一定要將所有的API都重新封裝,用到哪些才封裝哪些豺妓,這樣當(dāng)然是可以的惜互。不過還是挺困難的,百度地圖里面定義的類型太多了琳拭,哪怕是只用地圖這一個功能的API训堆,工作量都挺大。第二種白嘁,將百度地圖的.framework包拆開為.a和.h文件坑鱼。
上面提到,在.framework里面的頭文件沒辦法對外暴露絮缅,那么把.framework這層殼去掉呢姑躲?
第三種阿逃,為百度地圖的.framework包額外添加.h頭文件铭拧。
上面討論了,對.framework拆包這種方式不適用于百度地圖恃锉,所以還得想其他辦法搀菩。比如,.framework包不動破托,然后在.framework包外再額外加一份頭文件呢秕磷?事實(shí)證明,這樣完全是可以的炼团。最終就是以這種方式解決問題澎嚣。方法雖然很簡單,但是需要想法瘟芝。所以思路和想法非常重要易桃。最終封裝的形式如下圖所示,demo請點(diǎn)擊锌俱。
后續(xù)晤郑。。。
最近因?yàn)殡[私政策的原因造寝,需要再一次升級百度地圖磕洪。百度地圖已經(jīng)升級到6.5.1了。本來以為輕松替換一下靜態(tài)庫就可以完事诫龙,但是還是出幺蛾子了析显,百度地圖的幾個靜態(tài)庫替換之后,只要外面使用了百度地圖里面的類签赃,就會報(bào)類找不到錯誤谷异,也不知道百度地圖修改了什么導(dǎo)致的。如下圖所示:
經(jīng)過一番折騰锦聊,還是沒有搞定歹嘹,因此確定之前的方案不行了,得另覓出路了孔庭。于是又想到了前面說的第一種方案尺上,這種方案是兜底的,是一定可行的圆到,但是就是比較麻煩怎抛。那么有沒有既可行又簡單一點(diǎn)的方案呢?還真有构资。這次在第一種方案的基礎(chǔ)上進(jìn)行了改良和優(yōu)化,形成了第四種方案陨簇。
第四種吐绵,對百度地圖類進(jìn)行擴(kuò)展。
說通俗一點(diǎn)河绽,就是自己創(chuàng)建一個類己单,繼承百度地圖中需要用到的類,對外暴露自己創(chuàng)建的類耙饰,這樣就避免了在framework外面直接使用百度的類纹笼,就不會報(bào)上面的錯誤了。
例如苟跪,需要使用到百度地圖的BMKMapManager類廷痘,在BaiduMapKit.framework中自己創(chuàng)建一個MyMapManager類繼承自BMKMapManager,然后對外暴露MyMapManager頭文件件已,在外面調(diào)用的時候使用MyMapManager不用BMKMapManager了笋额。因?yàn)镸yMapManager類繼承自BMKMapManager,所以MyMapManager繼承了BMKMapManager所有的功能篷扩,而且還可以進(jìn)行一些擴(kuò)展和封裝兄猩,簡直再合適不過了。很完美地解決了問題,而且沒有增加多少工作量枢冤。我覺得和之前幾種方案比較鸠姨,這是最完美的一種方案了。現(xiàn)在的方案示意圖如下:
最后淹真,再附加一個遇到的坑讶迁。
BaiduMapAPI_Map.framework中包含一個資源包,mapapi.bundle需要放到主工程中趟咆,不然會報(bào)錯添瓷。
對外提供的frmework中帶資源包,不解決路徑問題值纱,真是很坑很拉胯鳞贷。報(bào)的莫名其妙的錯誤如下,沒有太多Log信息虐唠,調(diào)試了很久很久才發(fā)現(xiàn)是資源包不對搀愧,浪費(fèi)了很多寶貴的時間。
-[MTLDebugRenderCommandEncoder validateCommonDrawErrors:instanceCount:baseInstance:maxVertexID:]:5161: failed assertion `Draw Errors Validation
renderPipelineState must be set.
'
dyld4 config: DYLD_LIBRARY_PATH=/usr/lib/system/introspection DYLD_INSERT_LIBRARIES=/Developer/usr/lib/libBacktraceRecording.dylib:/Developer/usr/lib/libMainThreadChecker.dylib:/Developer/Library/PrivateFrameworks/GPUTools.framework/libglInterpose.dylib:/Developer/Library/PrivateFrameworks/DTDDISupport.framework/libViewDebuggerSupport.dylib
-[MTLDebugRenderCommandEncoder validateCommonDrawErrors:instanceCount:baseInstance:maxVertexID:]:5161: failed assertion `Draw Errors Validation
renderPipelineState must be set.
'