知識儲備:
一.庫(Library)
什么是庫?
庫是程序代碼的集合,是程序共享代碼的一種方式。根據(jù)源代碼的公開情況,庫可以分為開源庫和閉源庫。比如SDWebImage,AFNetworking,等可以看源碼的叫開源庫。閉源庫,不公開源代碼,是經(jīng)過編譯后的二進(jìn)制文件,看不到具體的實(shí)現(xiàn)。閉源庫又可以分為靜態(tài)庫和動態(tài)庫。庫說白了就是一段編譯好的二進(jìn)制代碼,加上頭文件就可以供別人使用。
二.靜態(tài)庫和動態(tài)庫
和多數(shù)人所熟悉的動態(tài)語言和靜態(tài)語言一樣,這里的所謂靜態(tài)和動態(tài)是相對編譯期和運(yùn)行期的
存在形式
靜態(tài)庫:.a 和 .framework ? ?動態(tài)庫: .dylib 和 .framework。 所以很多人誤以為.a就是靜態(tài)庫,.framework就是動態(tài)庫,不過系統(tǒng)的.framework都是動態(tài)庫
靜態(tài)庫和動態(tài)庫使用上的區(qū)別
靜態(tài)庫:鏈接時,靜態(tài)庫會被完整地復(fù)制到可執(zhí)行文件中,被多次使用就有多份冗余拷貝。編譯完成后,庫文件實(shí)際上就沒有作用了,也這是它的優(yōu)勢。當(dāng)然其缺點(diǎn)也很明顯,就是會明顯增大程序的體積。
動態(tài)庫:鏈接時不復(fù)制,程序運(yùn)行時由系統(tǒng)動態(tài)加載到內(nèi)存,供程序調(diào)用,系統(tǒng)只加載一次,供多個程序調(diào)用,節(jié)省內(nèi)存。由此可見動態(tài)庫又可以叫共享庫。注意:ios 8之前蘋果禁止iOS開發(fā)中使用自己創(chuàng)建的動態(tài)庫。原因估計(jì)是現(xiàn)在的iPhone,iPodTouch,iPad上面程序都是單進(jìn)程的,也就是某一時刻只有一個進(jìn)程在運(yùn)行,那么你寫個共享庫,共享給誰呢?你使用的時候只有你一個應(yīng)用程序存在,其他的應(yīng)該被掛起了,即便是可以同時多個進(jìn)程運(yùn)行,別人能使用你的共享庫里的東西嗎?但是iOS8之后,出現(xiàn)了Extension,動態(tài)庫有了用武之地,而且swift只支持動態(tài)庫的使用,造成這個原因主要是swift的運(yùn)行庫沒有被包含在iOS系統(tǒng)中,而是會被打包進(jìn)App中(這也是造成Swift App體積大的原因),靜態(tài)庫會導(dǎo)致最終的目標(biāo)程序中包含重復(fù)的運(yùn)行庫(這是蘋果自家的解釋)。
共同點(diǎn):靜態(tài)庫和動態(tài)庫都是閉源庫,只能拿來滿足某個功能的使用,不會暴露內(nèi)部具體的代碼信息,而從github上下載的第三方庫大多是開源庫
三.注意:
1.兩種庫都有framework的格式,但是它們長得一樣嗎?


2.當(dāng)你創(chuàng)建一個framework文件時,系統(tǒng)“默認(rèn)”是一個動態(tài)庫的格式,如果想做成靜態(tài)庫,需要在buildSetting中將Mach-O Type選項(xiàng)設(shè)置為Static Library就行了!

3. .a文件和.framework文件組成的區(qū)別:
.a文件是一個純二進(jìn)制文件,不能直接拿來使用,需要配合頭文件、資源文件一起使用。
將靜態(tài)庫打包的時候,只能打包代碼資源,但是圖片文件、本地json文件和xib等資源文件無法打包進(jìn)去,使用.a靜態(tài)庫的時候需要三個組成部分:.a文件+需要暴露的頭文件+資源文件;
.framework文件內(nèi)部除了有二進(jìn)制文件(如下圖黑色文件)之外還有其他的資源文件(相當(dāng)于:.framwork文件=黑色二進(jìn)制文件<.a文件+.h文件>+資源文件<圖片、以及本地的html5,json,plist等),可以直接拿來在工程中使用。
4.制作靜態(tài)庫時需要注意的幾點(diǎn):
(1)圖片資源的處理:兩種格式的靜態(tài)庫,一般都是把圖片文件單獨(dú)的放在一個.bundle文件中,一般.bundle的名字和.a或.framework的名字相同。(.bundle文件很好弄,在桌面上新建一個文件夾,把它重命名為XXX.bundle就可以了(選中文件->右鍵->顯示包內(nèi)容->拖拽添加圖片資源))。
(2)category是我們實(shí)際開發(fā)項(xiàng)目中經(jīng)常用到的,把category打成靜態(tài)庫是沒有問題的,但是在使用這個靜態(tài)庫的工程中,調(diào)用category中的方法時,會出現(xiàn)找不到該方法的運(yùn)行時錯誤:selector not recognized,解決辦法是:在使用靜態(tài)庫的工程中配置other linkerflags的值為-ObjC。
(3)如果一個靜態(tài)庫很復(fù)雜,需要暴露的.h比較多的話,就可以在靜態(tài)庫的內(nèi)部創(chuàng)建一個.h文件(一般這個.h文件的名字和靜態(tài)庫的名字相同),然后把所有需要暴露出來的.h文件都集中放在這個.h文件中,而那些原本需要暴露的.h都不需要再暴露了,只需要把.h暴露出來就可以了。
四.實(shí)戰(zhàn)制作庫








注:Build active Architecture Only為什么設(shè)置為NO?
在目標(biāo)設(shè)備上,執(zhí)行設(shè)備對應(yīng)的指令集。Build active Architecture Only 設(shè)置為YES,只會選擇編譯、鏈接對應(yīng)的指令集,設(shè)置為NO時,會涵蓋所有指令集,在必要的時候選擇執(zhí)行對應(yīng)的指令集。所以一般在Debug時會選擇設(shè)置為YES(效率會高點(diǎn),雖然也沒什么卵用),Release時會選擇設(shè)置為NO,以支持所有可能的架構(gòu)。
一般供人使用的庫為release版本,這個版本apple會做一些優(yōu)化。當(dāng)Buld Active Archite Only為No時,會編譯所有的版本arm7、armv7s、arm64。 各種指令集對應(yīng)的手機(jī)為armv7:iPhone 3GS/4/4s ?、armv7s:iPhone5 iPhone5c ?、arm64:iPhone5s以上、 i386: mac(模擬器)。另外在命令行可以用命令$?lipo?-info?.../XXX.a 來查看庫文件支持的指令集
將靜態(tài)庫分別選擇在模擬器和真機(jī)設(shè)備中編譯


從圖中可以看到編譯完后有兩個文件夾,對應(yīng)著真機(jī)和模擬器。接下來我們利用命令 lipo -create XXXX_1.a ?XXXX_2.a -output XXXX_all.a,將真機(jī)和模擬器的庫文件合并;(前面兩個.a為真機(jī)模擬器路徑;后面的為合并后想存放的路徑并為合并后的命名,一般名字和之前的一樣)

將.a二進(jìn)制文件和頭文件放在一起,靜態(tài)庫就這樣做完了。新建項(xiàng)目拉進(jìn)去就可以直接使用了。可能大家有疑問為什么最開始的時候要新建一個project,并是在targets里添加靜態(tài)庫,當(dāng)然你也可以直接按快捷鍵shift + command + N 來New一個Cocoa Touch Static Library,進(jìn)行開發(fā)制作。但是這樣無法測試你的靜態(tài)庫代碼,無法打斷點(diǎn)調(diào)試;如果你在你的工程里面添加靜態(tài)庫的話可以邊開發(fā)邊調(diào)試靜態(tài)庫的。