庫這一個概念由來已久,不是蘋果帶來的新東西。iOS平臺下對靜態(tài)庫和動態(tài)庫的使用又有一些不同。
一、先看一下庫的基本概念:
庫是共享程序代碼的方式,一般分為靜態(tài)庫和動態(tài)庫;庫實現(xiàn)了程序的模塊化,將某些特定的功能模塊化為庫的格式方便分享和使用!
1、那么靜態(tài)和動態(tài)有什么區(qū)別呢?
靜態(tài)庫:鏈接時完整地拷貝至可執(zhí)行文件中,被多次使用就有多份冗余拷貝。
動態(tài)庫:鏈接時不復(fù)制,程序運行時由系統(tǒng)動態(tài)加載到內(nèi)存,供程序調(diào)用,系統(tǒng)只加載一次,多個程序共用,節(jié)省內(nèi)存。
靜態(tài)庫和動態(tài)庫都是閉源庫,只能拿來滿足某個功能的使用,不會暴露內(nèi)部具體的代碼信息,而從github上下載的第三方庫大多是開源庫
二、iOS平臺下庫的不同與延伸:
1、靜態(tài)庫和動態(tài)庫的有兩種表現(xiàn)形式:
二進制庫:由源碼編譯成的二進制。靜態(tài)的.a結(jié)尾,動態(tài)的.dylib結(jié)尾
.framework: 我們一個庫的源碼編譯為二進制后,如果需要給其他人用,要將二進制+.h+資源文件(如果有)分發(fā)給其他人。也就是說只有二進制是不能用的。.framework其實就是一種打包形式,將二進制 ,.h 和資源文件做成.framwork的形式來分發(fā),這樣其他用戶直接將.framework直接拖到項目里就可以用了。
我們所說的動態(tài)與靜態(tài)其實是指的二進制的動態(tài)與靜態(tài),.framework的靜動態(tài)之分也是指其內(nèi)包含的二進制的靜動態(tài)之分。
從以上可以看到.framework的分發(fā)方式要更方便,所以人們都希望通過.framework的形式來提供給其他人用。
2、iOS下動態(tài)靜態(tài)庫的特別之處
1、wwdc2014之前:
只支持靜態(tài)二進制。
xcode只支持靜態(tài)二進制的制作,也即可以創(chuàng)建類型為 Static library的工程,然后將頭文件和資源文件一起分發(fā)給用戶。
xcode不支持創(chuàng)建framework創(chuàng)建的,只能自己手動創(chuàng)建偽framework來使用,也就是說仿照framework的目錄形式,將.h ,二進制,資源文件打包成.framework,通俗的來說就是將一個目錄形式符合framework的文件夾修改為.framework結(jié)尾,然后進行分發(fā)。
2、wwdc2014之后:
開始支持動態(tài)二進制 以及.framework的制作。(關(guān)于如何制作,這篇文章不涉及)
WWDC2014一個很大感觸是蘋果對iOS的開放態(tài)度:發(fā)布了Xcode6 beta和iOS8,iOS8上開放了允許使用動態(tài)庫、允許第三方鍵盤、App Extension等等。App Extension的出現(xiàn),可以為一個應(yīng)用創(chuàng)建插件,這樣主app和插件之間共享動態(tài)庫還是可行的。
注意:在iOS平臺下,自己制作的動態(tài)庫不能像系統(tǒng)提供的動態(tài)庫那樣在app之間動態(tài)鏈接,只能在自己app之內(nèi)使用,embed in app 中(即動態(tài)庫也會放到app 的bundle中)。
對于動態(tài)Framework,主app會用app的證書對引用的動態(tài)Framework進行簽名,然后放入到主bundle中,此時動態(tài)Framework和app的簽名證書是一樣的。app在加載動態(tài)Framework時,沙盒會對動態(tài)庫進行簽名驗證,驗證通過才可以加載。
對于上架的app,不能通過動態(tài)更新動態(tài)庫的方式來熱更新app,因為apple會對我們上傳的動態(tài)庫和app進行再簽名,此時的簽名不再是我們的證書簽名。我們通過服務(wù)器下載的新動態(tài)Framework不能通過沙盒簽名驗證(不能造出來和蘋果相同的簽名)。
對于企業(yè)版app,不經(jīng)過apple的再簽名,只要保證我們新更新的動態(tài)Framework簽名證書和我們的app簽名證書相同,就可以實現(xiàn)動態(tài)更新。實現(xiàn)可以參考?iOS 利用 Framework 進行動態(tài)更新。
3、動態(tài)庫Framework如何使用呢?
1、制作完動態(tài)Framework后,將Framework拖進自己的app工程中。
xcode幾個相關(guān)的配置:1、Build Settings ->Runnable Search Paths :指定從什么位置加載動態(tài)Framework,默認(rèn)為@executable_path/Frameworks,即在app主bundle/Frameworks下。2、BuildPhases->Embeded Frameworks,添加動態(tài)Framework,destination指向動態(tài)Framework拷貝到目的位置,默認(rèn)為app主bundle/Frameworks下,不同選項對應(yīng)不同位置。(Executables在mainBundle根目錄下,還有其他選項)
2、Build Settings ->Runnable Search Paths 修改為 @executable_path/,BuildPhases->Embeded Frameworks添加Framework,并修改destination為Executables.
3、代碼中獲取資源的方式,
NSBundle *bundle = [NSBundle bundleForClass:[PodName class]];//這種方式可以獲得mainBundle下(包括子目錄下)包括指定class的bundle
[UIImage imageNamed:name inBundle:bundle compatibleWithTraitCollection:nil]//從bundle中獲得指定的資源
4、為什么swift不能用靜態(tài)庫,只能用動態(tài)庫?
swift不再支持靜態(tài)庫,原因是Swift runtime 不在系統(tǒng)中,而是打包在各個app或者二進制中。所以如果要使用 Swift 靜態(tài)框架,由于 ABI 不兼容,所以我們將不得不在靜態(tài)包中再包含一次 runtime,產(chǎn)生重復(fù)問題,用swift寫的庫,必須通過動態(tài)鏈接。iOS 8才開放了動態(tài)庫的權(quán)限,這也就間接放棄了 iOS 7(自測結(jié)果:動態(tài)Framework 如果不包括資源文件,是可以在7上用的,如果有資源會引用不到資源)。swift runtime作為動態(tài)庫放入app中,其他swift動態(tài)庫可以動態(tài)的引用。
swift動態(tài)庫會將用到的相關(guān)的動態(tài)庫引入app中,導(dǎo)致swift的app變大。
5、cocoapods對swift的支持?
swfit只能使用動態(tài)庫,在Podfile頂部加上”use_frameworks!“,會將pod依賴都打成動態(tài)Framework。(其實打成Framework不是cocoapods做的,cocoapods做的只是根據(jù)這個標(biāo)識符,創(chuàng)建Framework類型的target,并且設(shè)置mach-o類型為dynamic;如果不加這個標(biāo)識符,則會創(chuàng)建Static library類型的target,并且設(shè)置mach-o類型為Static。xcode會根據(jù)target的設(shè)置去構(gòu)建出product)。
6、小命令
file 二進制 :如果輸出包含“dynamically linked shared library”,則說明是動態(tài)的,反之是靜態(tài)的。
lipo -info 二進制 :可以查看改二進制支持的cpu架構(gòu)。
總結(jié):
對oc來說,動態(tài)庫和靜態(tài)庫都可以使用,動態(tài)庫在程序啟動的時候也都會加載,沒有發(fā)現(xiàn)懶加載的方式。對于extension功能來說,動態(tài)庫有優(yōu)勢,可以共用動態(tài)庫。對swift來說只能用動態(tài)庫。
其實動態(tài)庫和靜態(tài)庫也沒有多么復(fù)雜,文中沒有介紹庫的制作方法,大家可以參考其他文章,以后相應(yīng)文章也會寫。
參考文章:
Objective-C和Swift混編的一些經(jīng)驗