注:文章轉(zhuǎn)自他處,原文地址:https://skyline75489.github.io/post/2015-8-14_ios_static_dynamic_framework_learning.htm
1.什么是庫?
庫(Library)說白了就是一段編譯好的二進(jìn)制代碼,加上頭文件就可以供別人使用。
還有,庫是共享程序代碼的方式,一般分為靜態(tài)庫和動(dòng)態(tài)庫。
靜態(tài)庫:鏈接時(shí)完整地拷貝至可執(zhí)行文件中,被多次使用就有多份冗余拷貝。
動(dòng)態(tài)庫:鏈接時(shí)不復(fù)制,程序運(yùn)行時(shí)由系統(tǒng)動(dòng)態(tài)加載到內(nèi)存,供程序調(diào)用,系統(tǒng)只加載一次,多個(gè)程序共用,節(jié)省內(nèi)存。
2.iOS里靜態(tài)庫形式
.a和.framework
3.iOS里動(dòng)態(tài)庫形式?
.dylib和.framework
4.framework為什么既是靜態(tài)庫又是動(dòng)態(tài)庫?
系統(tǒng)的.framework是動(dòng)態(tài)庫,我們自己建立的.framework是靜態(tài)庫。
5.a與.framework有什么區(qū)別?
.a是一個(gè)純二進(jìn)制文件,.framework中除了有二進(jìn)制文件之外還有資源文件。
.a文件不能直接使用,至少要有.h文件配合,.framework文件可以直接使用。
.a+.h+sourceFile =.framework。
建議用.framework.
6.什么場景下使用庫?
(1).某些代碼需要給別人使用,但是我們不希望別人看到源碼,就需要以庫的形式進(jìn)行封裝,只暴露出頭文件。
(2).對于某些不會進(jìn)行大的改動(dòng)的代碼,我們想減少編譯的時(shí)間,就可以把它打包成庫,因?yàn)閹焓且呀?jīng)編譯好的二進(jìn)制了,
編譯的時(shí)候只需要 Link 一下,不會浪費(fèi)編譯時(shí)間。
上面提到的庫在使用的時(shí)候需要 Link,Link 的方式有兩種,靜態(tài)和動(dòng)態(tài),于是便產(chǎn)生了靜態(tài)庫和動(dòng)態(tài)庫。
7.靜態(tài)庫
7.1靜態(tài)庫的介紹
靜態(tài)庫即靜態(tài)鏈接庫(Windows 下的 .lib,Linux 和 Mac 下的 .a)。之所以叫做靜態(tài),是因?yàn)殪o態(tài)庫在編譯的時(shí)候會被直接拷貝一份,復(fù)制到目標(biāo)程序里,這段代碼在目標(biāo)程序里就不會再改變了。
靜態(tài)庫的好處很明顯,編譯完成之后,庫文件實(shí)際上就沒有作用了。目標(biāo)程序沒有外部依賴,直接就可以運(yùn)行。當(dāng)然其缺點(diǎn)也很明顯,就是會使用目標(biāo)程序的體積增大。
7.2為什么要使用靜態(tài)庫?
方便共享代碼,便于合理使用。
實(shí)現(xiàn)iOS程序的模塊化。可以把固定的業(yè)務(wù)模塊化成靜態(tài)庫。
和別人分享你的代碼庫,但不想讓別人看到你代碼的實(shí)現(xiàn)。
開發(fā)第三方sdk的需要。
7.3制作靜態(tài)庫時(shí)的幾點(diǎn)注意
1 注意理解:無論是.a靜態(tài)庫還.framework靜態(tài)庫,我們需要的都是二進(jìn)制文件+.h+其它資源文件的形式,不同的是,.a本身就是二進(jìn)制文件,需要我們自己配上.h和其它文件才能使用,而.framework本身已經(jīng)包含了.h和其它文件,可以直接使用。
2 圖片資源的處理:兩種靜態(tài)庫,一般都是把圖片文件單獨(dú)的放在一個(gè).bundle文件中,一般.bundle的名字和.a或.framework的名字相同。.bundle文件很好弄,新建一個(gè)文件夾,把它改名為.bundle就可以了,右鍵,顯示包內(nèi)容可以向其中添加圖片資源。
3 category是我們實(shí)際開發(fā)項(xiàng)目中經(jīng)常用到的,把category打成靜態(tài)庫是沒有問題的,但是在用這個(gè)靜態(tài)庫的工程中,調(diào)用category中的方法時(shí)會有找不到該方法的運(yùn)行時(shí)錯(cuò)誤(selector not recognized),解決辦法是:在使用靜態(tài)庫的工程中配置other linker flags的值為-ObjC。
4 如果一個(gè)靜態(tài)庫很復(fù)雜,需要暴露的.h比較多的話,就可以在靜態(tài)庫的內(nèi)部創(chuàng)建一個(gè).h文件(一般這個(gè).h文件的名字和靜態(tài)庫的名字相同),然后把所有需要暴露出來的.h文件都集中放在這個(gè).h文件中,而那些原本需要暴露的.h都不需要再暴露了,只需要把.h暴露出來就可以了。
5.注意:動(dòng)態(tài)庫可以使用但是不能上架!
而且使用的時(shí)候必須在添加動(dòng)態(tài)庫的工程中的 General-->Embedded Binaries 中添加一下,具體如圖所示:

那么如何想使用動(dòng)態(tài)庫上架呢?我們只需要在制作的時(shí)候?qū)⑵渚幾g成靜態(tài)庫。在Buid Settins-->Mach-O Type--> Static Library具體如圖:

同樣不要忘了編譯,這樣編譯出來的庫就是靜態(tài)庫了。我們就可以像靜態(tài)庫一樣在工程中使用了。
8.動(dòng)態(tài)庫
8.1 什么是動(dòng)態(tài)庫
動(dòng)態(tài)庫即動(dòng)態(tài)鏈接庫(Windows 下的 .dll,Linux 下的 .so,Mac 下的 .dylib/.tbd)。與靜態(tài)庫相反,動(dòng)態(tài)庫在編譯時(shí)并不會被拷貝到目標(biāo)程序中,目標(biāo)程序中只會存儲指向動(dòng)態(tài)庫的引用。等到程序運(yùn)行時(shí),動(dòng)態(tài)庫才會被真正加載進(jìn)來。
8.2動(dòng)態(tài)庫的優(yōu)缺點(diǎn)
不需要拷貝到目標(biāo)程序中,不會影響目標(biāo)程序的體積,而且同一份庫可以被多個(gè)程序使用(因?yàn)檫@個(gè)原因,動(dòng)態(tài)庫也被稱作共享庫)。同時(shí),編譯時(shí)才載入的特性,也可以讓我們隨時(shí)對庫進(jìn)行替換,而不需要重新編譯代碼。動(dòng)態(tài)庫帶來的問題主要是,動(dòng)態(tài)載入會帶來一部分性能損失,使用動(dòng)態(tài)庫也會使得程序依賴于外部環(huán)境。如果環(huán)境缺少動(dòng)態(tài)庫或者庫的版本不正確,就會導(dǎo)致程序無法運(yùn)行(Linux 下喜聞樂見的 lib not found 錯(cuò)誤)。
9.iOS Framework
9.1什么是framework
除了上面提到的 .a 和 .dylib/.tbd 之外,Mac OS/iOS 平臺還可以使用 Framework。
Framework :實(shí)際上是一種打包方式,將庫的二進(jìn)制文件,頭文件和有關(guān)的資源文件打包到一起,方便管理和分發(fā)。
framework是Cocoa/Cocoa Touch程序中使用的一種資源打包方式,可以將將代碼文件、頭文件、資源文件、說明文檔等集中在一起,方便開發(fā)者使用。
Cocoa/Cocoa Touch開發(fā)框架本身提供了大量的Framework,比如Foundation.framework/UIKit.framework/AppKit.framework等。需要注意的是,這些framework無一例外都是動(dòng)態(tài)庫。
平時(shí)我們用的第三方SDK的framework都是靜態(tài)庫,真正的動(dòng)態(tài)庫是上不了AppStore的。
9.2framework為什么既是靜態(tài)庫又是動(dòng)態(tài)庫?
系統(tǒng)的.framework是動(dòng)態(tài)庫,我們自己建立的.framework是靜態(tài)庫。
9.3framework背景介紹
(1).在 iOS 8 之前,iOS 平臺不支持使用動(dòng)態(tài) Framework,開發(fā)者可以使用的 Framework 只有蘋果自家的 UIKit.Framework,F(xiàn)oundation.Framework 等。
?(2) ?.iOS 8/Xcode 6 推出之后,iOS 平臺添加了動(dòng)態(tài)庫的支持,同時(shí) Xcode 6 也原生自帶了 Framework 支持(動(dòng)態(tài)和靜態(tài)都可以)。
為什么 iOS 8 要添加動(dòng)態(tài)庫的支持?唯一的理由大概就是 Extension 的出現(xiàn)。Extension 和 App 是兩個(gè)分開的可執(zhí)行文件,同時(shí)需要共享代碼,這種情況下動(dòng)態(tài)庫的支持就是必不可少的了。但是這種動(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。
10. CocoaPods 的做法
在純 ObjC 的項(xiàng)目中,CocoaPods 使用編譯靜態(tài)庫 .a 方法將代碼集成到項(xiàng)目中。在 Pods 項(xiàng)目中的每個(gè) target 都對應(yīng)這一個(gè) Pod 的靜態(tài)庫。不過在編譯過程中并不會真的產(chǎn)出 .a 文件。如果需要 .a 文件的話,可以參考這里,或者使用CocoasPods-Packager這個(gè)插件。
當(dāng)不想發(fā)布代碼的時(shí)候,也可以使用 Framework 發(fā)布 Pod,CocoaPods 提供了vendored_framework
選項(xiàng)來使用第三方 Framework,具體的做法可以參考這里1和這里2。
對于 Swift 項(xiàng)目,CocoaPods 提供了動(dòng)態(tài) Framework 的支持,通過 use_frameworks!
[更多參考資料]
WWDC2014之iOS使用動(dòng)態(tài)庫中有很詳細(xì)的創(chuàng)建動(dòng)態(tài)庫和使用動(dòng)態(tài)庫的教程。
博客:http://geeklu.com/2014/02/objc-lib/
https://stackoverflow.com/questions/2649334/difference-between-static-and-shared-libraries
https://stackoverflow.com/questions/25080914/will-ios-8-support-dynamic-linking