背景: 在項(xiàng)目中使用OC和Swift混編, 用Cocoapods導(dǎo)入SwiftyJSON時(shí)需要在PodFile里面使用use_frameworks!才能安裝, 導(dǎo)入成功后編譯項(xiàng)目報(bào).h 未能發(fā)現(xiàn)的錯(cuò)誤. 經(jīng)過一頓google之后得知如果在cocoapods 里面不使用 use_frameworks!, 則是通過static libraries 這個(gè)方式來管理pod的代碼. 而如果使用了use_frameworks!, 則cocoapods 使用frameworks 來取代static libraries 方式. 所以這就引出了靜態(tài)庫(kù)和Framework這兩個(gè)概念, 然后干脆就查了一下靜態(tài)庫(kù), 動(dòng)態(tài)庫(kù),Framework的概念.
靜態(tài)庫(kù)與動(dòng)態(tài)庫(kù)的區(qū)別
首先來看什么是庫(kù),庫(kù)(Library)說白了就是一段編譯好的二進(jìn)制代碼狼电,加上頭文件就可以供別人使用蜒灰。
什么時(shí)候我們會(huì)用到庫(kù)呢?一種情況是某些代碼需要給別人使用肩碟,但是我們不希望別人看到源碼强窖,就需要以庫(kù)的形式進(jìn)行封裝,只暴露出頭文件削祈。另外一種情況是翅溺,對(duì)于某些不會(huì)進(jìn)行大的改動(dòng)的代碼,我們想減少編譯的時(shí)間髓抑,就可以把它打包成庫(kù)咙崎,因?yàn)閹?kù)是已經(jīng)編譯好的二進(jìn)制了,編譯的時(shí)候只需要 Link 一下吨拍,不會(huì)浪費(fèi)編譯時(shí)間褪猛。
上面提到庫(kù)在使用的時(shí)候需要 Link,Link 的方式有兩種羹饰,靜態(tài)和動(dòng)態(tài)伊滋,于是便產(chǎn)生了靜態(tài)庫(kù)和動(dòng)態(tài)庫(kù)。
靜態(tài)庫(kù)
靜態(tài)庫(kù)即靜態(tài)鏈接庫(kù)(Windows 下的 .lib队秩,Linux 和 Mac 下的 .a)笑旺。之所以叫做靜態(tài),是因?yàn)殪o態(tài)庫(kù)在編譯的時(shí)候會(huì)被直接拷貝一份馍资,復(fù)制到目標(biāo)程序里筒主,這段代碼在目標(biāo)程序里就不會(huì)再改變了。
靜態(tài)庫(kù)的好處很明顯鸟蟹,編譯完成之后物舒,庫(kù)文件實(shí)際上就沒有作用了。目標(biāo)程序沒有外部依賴戏锹,直接就可以運(yùn)行。當(dāng)然其缺點(diǎn)也很明顯火诸,就是會(huì)使用目標(biāo)程序的體積增大锦针。
動(dòng)態(tài)庫(kù)
動(dòng)態(tài)庫(kù)即動(dòng)態(tài)鏈接庫(kù)(Windows 下的 .dll,Linux 下的 .so,Mac 下的 .dylib/.tbd)奈搜。與靜態(tài)庫(kù)相反悉盆,動(dòng)態(tài)庫(kù)在編譯時(shí)并不會(huì)被拷貝到目標(biāo)程序中,目標(biāo)程序中只會(huì)存儲(chǔ)指向動(dòng)態(tài)庫(kù)的引用馋吗。等到程序運(yùn)行時(shí)焕盟,動(dòng)態(tài)庫(kù)才會(huì)被真正加載進(jìn)來。
動(dòng)態(tài)庫(kù)的優(yōu)點(diǎn)是宏粤,不需要拷貝到目標(biāo)程序中脚翘,不會(huì)影響目標(biāo)程序的體積,而且同一份庫(kù)可以被多個(gè)程序使用(因?yàn)檫@個(gè)原因绍哎,動(dòng)態(tài)庫(kù)也被稱作共享庫(kù))来农。同時(shí),編譯時(shí)才載入的特性崇堰,也可以讓我們隨時(shí)對(duì)庫(kù)進(jìn)行替換沃于,而不需要重新編譯代碼。動(dòng)態(tài)庫(kù)帶來的問題主要是海诲,動(dòng)態(tài)載入會(huì)帶來一部分性能損失繁莹,使用動(dòng)態(tài)庫(kù)也會(huì)使得程序依賴于外部環(huán)境。如果環(huán)境缺少動(dòng)態(tài)庫(kù)或者庫(kù)的版本不正確特幔,就會(huì)導(dǎo)致程序無法運(yùn)行(Linux 下喜聞樂見的 lib not found 錯(cuò)誤)咨演。
iOS Framework
除了上面提到的 .a 和 .dylib/.tbd 之外,Mac OS/iOS 平臺(tái)還可以使用 Framework敬辣。Framework 實(shí)際上是一種打包方式雪标,將庫(kù)的二進(jìn)制文件,頭文件和有關(guān)的資源文件打包到一起溉跃,方便管理和分發(fā)村刨。
在 iOS 8 之前,iOS 平臺(tái)不支持使用動(dòng)態(tài) Framework撰茎,開發(fā)者可以使用的 Framework 只有蘋果自家的 UIKit.Framework嵌牺,F(xiàn)oundation.Framework 等。這種限制可能是出于安全的考慮龄糊。換一個(gè)角度講逆粹,因?yàn)?iOS 應(yīng)用都是運(yùn)行在沙盒當(dāng)中,不同的程序之間不能共享代碼炫惩,同時(shí)動(dòng)態(tài)下載代碼又是被蘋果明令禁止的僻弹,沒辦法發(fā)揮出動(dòng)態(tài)庫(kù)的優(yōu)勢(shì),實(shí)際上動(dòng)態(tài)庫(kù)也就沒有存在的必要了他嚷。
由于上面提到的限制蹋绽,開發(fā)者想要在 iOS 平臺(tái)共享代碼芭毙,唯一的選擇就是打包成靜態(tài)庫(kù) .a 文件,同時(shí)附上頭文件(例如微信的SDK)卸耘。但是這樣的打包方式不夠方便退敦,使用時(shí)也比較麻煩,大家還是希望共享代碼都能能像 Framework 一樣蚣抗,直接扔到工程里就可以用侈百。于是人們想出了各種奇技淫巧去讓 Xcode Build 出 iOS 可以使用的 Framework,這種方法產(chǎn)生的 Framework 還有 “偽”(Fake) Framework 和 “真”(Real) Framework 的區(qū)別翰铡。
iOS 8/Xcode 6 推出之后钝域,iOS 平臺(tái)添加了動(dòng)態(tài)庫(kù)的支持,同時(shí) Xcode 6 也原生自帶了 Framework 支持(動(dòng)態(tài)和靜態(tài)都可以)两蟀,上面提到的的奇技淫巧也就沒有必要了网梢。為什么 iOS 8 要添加動(dòng)態(tài)庫(kù)的支持?唯一的理由大概就是 Extension 的出現(xiàn)赂毯。Extension 和 App 是兩個(gè)分開的可執(zhí)行文件战虏,同時(shí)需要共享代碼,這種情況下動(dòng)態(tài)庫(kù)的支持就是必不可少的了党涕。但是這種動(dòng)態(tài) Framework 和系統(tǒng)的 UIKit.Framework 還是有很大區(qū)別烦感。系統(tǒng)的 Framework 不需要拷貝到目標(biāo)程序中,我們自己做出來的 Framework 哪怕是動(dòng)態(tài)的膛堤,最后也還是要拷貝到 App 中(App 和 Extension 的 Bundle 是共享的)手趣,因此蘋果又把這種 Framework 稱為 Embedded Framework。
Swift 支持
跟著 iOS8 / Xcode 6 同時(shí)發(fā)布的還有 Swift肥荔。如果要在項(xiàng)目中使用外部的代碼绿渣,可選的方式只有兩種,一種是把代碼拷貝到工程中燕耿,另一種是用動(dòng)態(tài) Framework中符。使用靜態(tài)庫(kù)是不支持的。
造成這個(gè)問題的原因主要是 Swift 的運(yùn)行庫(kù)沒有被包含在 iOS 系統(tǒng)中誉帅,而是會(huì)打包進(jìn) App 中(這也是造成 Swift App 體積大的原因)淀散,靜態(tài)庫(kù)會(huì)導(dǎo)致最終的目標(biāo)程序中包含重復(fù)的運(yùn)行庫(kù)(這是蘋果自家的解釋)。同時(shí)拷貝 Runtime 這種做法也會(huì)導(dǎo)致在純 ObjC 的項(xiàng)目中使用 Swift 庫(kù)出現(xiàn)問題蚜锨。蘋果聲稱等到 Swift 的 Runtime 穩(wěn)定之后會(huì)被加入到系統(tǒng)當(dāng)中档插,到時(shí)候這個(gè)限制就會(huì)被去除了。
CocoaPods 的做法
在純 ObjC 的項(xiàng)目中亚再,CocoaPods 使用編譯靜態(tài)庫(kù) .a 方法將代碼集成到項(xiàng)目中郭膛。在 Pods 項(xiàng)目中的每個(gè) target 都對(duì)應(yīng)這一個(gè) Pod 的靜態(tài)庫(kù)。不過在編譯過程中并不會(huì)真的產(chǎn)出 .a 文件
當(dāng)不想發(fā)布代碼的時(shí)候氛悬,也可以使用 Framework 發(fā)布 Pod饲鄙,CocoaPods 提供了vendored_framework 選項(xiàng)來使用第三方 Framework
對(duì)于 Swift 項(xiàng)目凄诞,CocoaPods 提供了動(dòng)態(tài) Framework 的支持,通過 use_frameworks!選項(xiàng)控制
參考1: iOS 靜態(tài)庫(kù)忍级,動(dòng)態(tài)庫(kù)與 Framework 淺析
參考2:博客(可能需要翻墻看)