【原創(chuàng)博文,轉(zhuǎn)載請(qǐng)注明出處!】
軟件開(kāi)發(fā)中庫(kù)的分類(lèi)無(wú)非就是開(kāi)源庫(kù)與閉源庫(kù)。在iOS領(lǐng)域,常見(jiàn)的開(kāi)源庫(kù)比如AFN、SDWebImage等。閉源庫(kù)如支付寶SDK、百度地圖等。今天本文所討論的靜態(tài)庫(kù)與動(dòng)態(tài)庫(kù)都屬于閉源庫(kù)。
靜態(tài)庫(kù)與動(dòng)態(tài)庫(kù)的基本常識(shí):
1. 靜態(tài)庫(kù)的存在形式?
① .a
② .framework
2. 動(dòng)態(tài)庫(kù)的存在形式?
① .dylib
② .tbd
③ .framework
3. 靜態(tài)庫(kù)與動(dòng)態(tài)庫(kù)的區(qū)別:
① 靜態(tài)庫(kù)在鏈接時(shí), 會(huì)被完整的復(fù)制到可執(zhí)行文件中; 被多次使用, 就有多份拷貝;
② 動(dòng)態(tài)庫(kù)則不會(huì)復(fù)制, 只有一份. 程序運(yùn)行時(shí)動(dòng)態(tài)加載到內(nèi)存; 系統(tǒng)只加載一次, 多個(gè)程序共用, 節(jié)省內(nèi)存;
③ 但是項(xiàng)目中如果使用到自己的動(dòng)態(tài)庫(kù), 不允許上架!!!
④ 后了在 WWDC2014上,蘋(píng)果公布了對(duì)iOS8開(kāi)放動(dòng)態(tài)加載dylib的接口,也就是說(shuō) 開(kāi)放了動(dòng)態(tài)庫(kù)掛載。
4. 靜態(tài)庫(kù)應(yīng)用場(chǎng)景:
① 保護(hù)核心代碼;
② 提高工程的編譯速度;
③ 將MRC的項(xiàng)目,打包成靜態(tài)庫(kù), 可以在ARC下直接使用, 不需要轉(zhuǎn)換。
5. 靜態(tài)庫(kù)的特點(diǎn):
① .a + .h文件
② 看不到具體實(shí)現(xiàn)的代碼
<1> Cocoa Touch Static Library中.a類(lèi)型的靜態(tài)庫(kù)
接下來(lái)我們?cè)赬code中新建一個(gè)靜態(tài)庫(kù)文件StaticLib。與一般新建App項(xiàng)目不一樣,這次我們打開(kāi)Xcode之后,在Framework & Library欄目下面選中Cocoa Touch Static Library。如下圖所示:

接下來(lái)我們?cè)陟o態(tài)庫(kù)里面新建一個(gè)文件,如LogTool并提供一個(gè)方法+ (void)log;

這些操作之后,我們編譯一下(Command+B)就可以得到靜態(tài)庫(kù)文件libStaticLib.a。靜態(tài)庫(kù)文件的名字取決于我們新建靜態(tài)庫(kù)工程所取得名字,默認(rèn)為libXXX.a(XXX就是新建靜態(tài)庫(kù)項(xiàng)目的名稱(chēng))。

默認(rèn)生成的靜態(tài)庫(kù)不會(huì)包含頭文件。添加頭文件的方式有兩種,可以手動(dòng)將頭文件拖到.a文件所在的位置,但是對(duì)于靜態(tài)庫(kù)的頭文件較多,這樣會(huì)比較復(fù)雜。更簡(jiǎn)單的方式是通過(guò)Bulid Phases設(shè)置。選中Copy Files下面的“+”按鈕,即可將靜態(tài)庫(kù)所需的頭文件全部導(dǎo)入。Xcode默認(rèn)會(huì)將頭文件放到SubPath所指定的include文件夾中,可以刪掉這個(gè)path,頭文件就會(huì)自動(dòng)導(dǎo)入到.a所在的位置。操作看截圖所示:

前面我們介紹過(guò)不同iOS設(shè)備芯片架構(gòu)不同,所以靜態(tài)庫(kù)文件需要支持不同的架構(gòu)。我們通過(guò)終端查看一下當(dāng)前的libStaticLib.a支持的架構(gòu)
Rephontil:~ zhouyong$ cd /Users/zhouyong/Desktop/Demo/StaticLibProject/TestStaticLib/StatilLib
Rephontil:StatilLib zhouyong$ lipo -info libStaticLib.a
input file libStaticLib.a is not a fat file
Non-fat file: libStaticLib.a is architecture: x86_64
因?yàn)槭褂玫氖莍Phone7模擬器,屬于X86_64架構(gòu),所以默認(rèn)支持這個(gè)。如果需要支持早期的設(shè)備如iPhone5等,則通過(guò)Build Settings,找到Build Active Architecture Only并設(shè)置為No,這樣就可以支持出當(dāng)前選擇的模擬器型號(hào)之外的多種架構(gòu)了。

上面獲得的靜態(tài)庫(kù)只支持模擬器設(shè)備,對(duì)于真機(jī)設(shè)備,我們需要選中Generic iOS Device進(jìn)行編譯,最終得到支持真機(jī)設(shè)備運(yùn)行的靜態(tài)庫(kù)。
各種不同機(jī)型設(shè)備的架構(gòu)如下表所舉:

如果靜態(tài)庫(kù)里面有資源文件怎么辦?
Tips as follows:
如果靜態(tài)庫(kù)需要放入資源文件,非常不建議直接將這些資源文件放入靜態(tài)庫(kù)路徑下不做任何處理。 最合理的方法:將存放這些資源的文件夾改名為resource.bundle(一定要是.bundle)。這樣在項(xiàng)目中導(dǎo)入靜態(tài)庫(kù)的時(shí)候,一起導(dǎo)入resource.bundle文件(好處是在編譯生成xxx.app文件的時(shí)候,工程資源文件如果與靜態(tài)庫(kù)資源文件有重名,也不會(huì)覆蓋其中任一方的資源文件,以后就這么做)。
多種架構(gòu)靜態(tài)庫(kù)的合成與分解
1.合成靜態(tài)庫(kù)文件
對(duì)于模擬器和真機(jī)設(shè)備,編譯之后得到兩份靜態(tài)庫(kù)。通過(guò)"lipo -create Debug-iphonesimulator.a(路徑) Debug-iphoneos(路徑) -output xxx.a"命令在終端合成最終的靜態(tài)庫(kù)文件xxx.a。合成之后的xxx.a即能支持模擬器,又可以支持真機(jī)。
Rephontil:Debug-iphoneos zhouyong$ cd /Users/zhouyong/Library/Developer/Xcode/DerivedData/StaticLib-ccrfruuotxbhdydkrcdebfkcvqwp/Build/Products/CombineLibrary
Rephontil:CombineLibrary zhouyong$ lipo -create /Users/zhouyong/Library/Developer/Xcode/DerivedData/StaticLib-ccrfruuotxbhdydkrcdebfkcvqwp/Build/Products/Debug-iphoneos/libStaticLib.a /Users/zhouyong/Library/Developer/Xcode/DerivedData/StaticLib-ccrfruuotxbhdydkrcdebfkcvqwp/Build/Products/Debug-iphonesimulator/libStaticLib.a -output libStaticLib.a
注意
由于合成以后靜態(tài)庫(kù)文件的體積是之前支持模擬器和支持真機(jī)靜態(tài)庫(kù)文件的總和,如果靜態(tài)庫(kù)體積本身就很大,合成模擬器和真機(jī)環(huán)境的靜態(tài)庫(kù)就顯得不明智了。開(kāi)發(fā)者自己選擇打包的時(shí)候需要包含的靜態(tài)庫(kù)即可。
2.靜態(tài)庫(kù)廋身
如果合成之后的靜態(tài)庫(kù)支持i386 arm64 x86等架構(gòu),但是我們只想要i386這一種架構(gòu),可以通過(guò)“l(fā)ipo -thin -output”命令將之前合成的fat靜態(tài)庫(kù)瘦身成只支持i386架構(gòu)的庫(kù)(也就是同時(shí)移除了arm64 x86兩種架構(gòu)),thin指令具體操作如下:
lipo -thin i386 庫(kù)的路徑 -output 新的庫(kù)名
另外:如果我們只是希望從合成的庫(kù)中移除i386架構(gòu),保留arm64 x86兩種架構(gòu),則可以通過(guò)“l(fā)ipo -remove -output”指令單獨(dú)移除某一種架構(gòu)。remove指令具體操作如下:
lipo -remove i386 庫(kù)的路徑 -output 新的庫(kù)名
<2> Cocoa Touch Framework中 .framework類(lèi)型的靜態(tài)庫(kù)
為了方便靜態(tài)庫(kù)的測(cè)試,我們先創(chuàng)建一個(gè)iOS項(xiàng)目,然后再在項(xiàng)目中創(chuàng)建一個(gè)靜態(tài)庫(kù)。

按照?qǐng)D中步驟,我們便可創(chuàng)建一個(gè).framework類(lèi)型的庫(kù)。
注意:
①由于默認(rèn)情況下生成的.framework庫(kù)是動(dòng)態(tài)的,需要在Build Settings里設(shè)置mach為Static Library。
②設(shè)置Build Active Architecture Only 為NO,以導(dǎo)出支持多種架構(gòu)庫(kù)。
③設(shè)置.framework暴露出來(lái)的頭文件。


通過(guò)show in finder查看生成的靜態(tài)庫(kù)文件。

將生成的靜態(tài)庫(kù)文件拖入新的項(xiàng)目中,便可使用。需要注意的是引入頭文件的方式有所變化。格式為:“#import <.framework庫(kù)名/xxx.h>”

