夯實(shí)基礎(chǔ) 砥礪前行 ---iOS靜態(tài)庫的開發(fā)

什么是庫?

庫是共享程序代碼的方式,一般分為動(dòng)態(tài)庫和靜態(tài)庫。

  • 靜態(tài)庫:.a和.framework
  • 動(dòng)態(tài)庫:.dylib和.framework

在實(shí)際的項(xiàng)目開發(fā)中,經(jīng)常會(huì)使用到庫,庫分為靜態(tài)庫和動(dòng)態(tài)庫兩種。和多數(shù)人所熟悉的動(dòng)態(tài)語言和靜態(tài)語言一樣,這里的所謂靜態(tài)和動(dòng)態(tài)是相對編譯期和運(yùn)行期的:靜態(tài)庫在程序編譯時(shí)會(huì)被鏈接到目標(biāo)代碼中,程序運(yùn)行時(shí)將不再需要改靜態(tài)庫;而動(dòng)態(tài)庫在程序編譯時(shí)并不會(huì)被鏈接到目標(biāo)代碼中,只是在程序運(yùn)行時(shí)才被載入,因?yàn)樵诔绦蜻\(yùn)行期間還需要?jiǎng)討B(tài)庫的存在。

靜態(tài)庫和動(dòng)態(tài)庫區(qū)別

  • 靜態(tài)庫:鏈接時(shí),靜態(tài)庫會(huì)被完整的復(fù)制到可執(zhí)行文件中,被多次使用就又多份冗余拷貝
  • 動(dòng)態(tài)庫:鏈接時(shí)不復(fù)制,程序運(yùn)行時(shí)由系統(tǒng)動(dòng)態(tài)加載到內(nèi)存,供程序調(diào)用,系統(tǒng)只會(huì)加載一次,多個(gè)程序共用,節(jié)省內(nèi)存

注意:項(xiàng)目中如果使用了自制的動(dòng)態(tài)庫(framework)不能被上傳到AppStore

.a和.framewrok有什么區(qū)別?

  • .a是一個(gè)純二進(jìn)制文件,.framework是一個(gè)文件夾,文件夾中除了有二進(jìn)制文件之外還有資源文件。* .a文件不能直接使用,至少要有.h文件配合,.framework文件可以直接使用。* .a + .h + sourceFile = .framework。

靜態(tài)庫的應(yīng)用場景

  • 希望更多的開發(fā)者在程序中集成,但是又不想公布自己的核心技術(shù);對外暴露統(tǒng)一接口,開發(fā)者調(diào)用靜態(tài)庫即可。
  • 項(xiàng)目開發(fā)中有一部分核心代碼,非核心開發(fā)人員倘若離職,對于公司來說是一種損失

1. a靜調(diào)庫的編譯

1.靜態(tài)庫的創(chuàng)建:左側(cè)為.framework 右側(cè)為.a

1.png

2.創(chuàng)建工具類,并暴露接口新建工具類,并在buildPhrase中添加需要暴露的.h文件

2.png

3.分別在不同的環(huán)境下編譯,從而得到支持不同環(huán)境的靜調(diào)庫

3.png

4.查看不同環(huán)境下的靜態(tài)庫


4.png

在不同的文件夾下可以查看不同環(huán)境使用的.a靜調(diào)庫文件,新建項(xiàng)目,將.a文件拖拽到項(xiàng)目中估計(jì)可使用

5.png

靜態(tài)庫中的架構(gòu)問題

當(dāng)使用真機(jī)環(huán)境的.a文件在模擬中編譯或者運(yùn)行時(shí),會(huì)報(bào)架構(gòu)的錯(cuò)誤 。

  • 設(shè)備的CPU架構(gòu)

  • 不同的設(shè)備使用的CPU不同

  • CPU的不同就造成使用的CPU架構(gòu)(即指令集)不同

  • 靜態(tài)庫有其支持的CPU架構(gòu)

    • 如果靜態(tài)庫在其不支持的CPU架構(gòu)上面運(yùn)行就會(huì)報(bào)錯(cuò)
  • 模擬器使用的CPU架構(gòu)

  • iPhone4s-iPhone5:i386

  • iPhone5s-iPhone6Plus:x86_64

  • 真機(jī)使用的CPU架構(gòu)

  • iPhone3gs-iPhone4sP:armv7

  • iPhone5-iPhone5c:armv7s

  • iPhone5s-iPhone6plus:arm64

  • 注意: 支持armv7的靜態(tài)庫可以在armv7s上正常使用* 查看靜態(tài)庫的架構(gòu)(終端命令)
    $ lipo -info 靜態(tài)庫地址

  • 合并靜態(tài)庫
    $ lipo create 靜態(tài)庫1 靜態(tài)庫2 output 合并后的靜態(tài)庫

如何使靜調(diào)庫支持多種CPU架構(gòu)

想要制作的靜態(tài)庫既支持i386架構(gòu)也支持x86_64架構(gòu),有兩種解決方法.

  1. 修改靜態(tài)庫的編譯環(huán)境并重新編譯


    6.png

    在termnal中使用命令將多個(gè)靜態(tài)庫合并

 $ lipo -create Debug-iphoneos/libStaticLibrary.a Debug-iphonesimulator/libStaticLibrary.a -output libnewstatic.a

合并后的靜調(diào)庫的大小>=合并之前靜態(tài)庫大小之和
開發(fā)環(huán)境:需要支持真機(jī)以及模擬器的靜態(tài)庫
生產(chǎn)環(huán)境:只需要支持真機(jī)的靜態(tài)庫即可

2 .framework靜態(tài)庫的編譯

第一步與.a文件文件創(chuàng)建一樣,選擇framework,點(diǎn)開以后發(fā)現(xiàn),項(xiàng)目中已經(jīng)存在一個(gè)與項(xiàng)目名稱一樣的主頭文件(這是蘋果推薦的方式 )
1.將需要暴露的頭文件添加到public(拖入即可)

1.png

注意:將需要暴露的頭文件放到主頭文件中
2.步驟跟.a文件一致,分別在真機(jī)以及模擬器環(huán)境編譯,得到兩個(gè)不同環(huán)境的.framework

2.png

3.使用.framework并運(yùn)行

3.png

查看控制臺(tái)發(fā)現(xiàn)報(bào)錯(cuò),發(fā)現(xiàn)制作的framework為動(dòng)態(tài)庫,動(dòng)態(tài)庫的使用,需要在target中手動(dòng)添加動(dòng)態(tài)庫。(只能作為測試使用,蘋果禁止自制的動(dòng)態(tài)庫上架,上架前切記修改為靜態(tài)庫)
4.修改編譯環(huán)境,編譯靜態(tài)庫buildsetting 搜索mach 并修改

4.png

使用該方法制作的靜態(tài)庫,可以運(yùn)行,但是在4s中是無法運(yùn)行的,會(huì)報(bào)CPU架構(gòu)的錯(cuò)誤,通過$lipo -info StaticFramework查看framework所支持的架構(gòu),目前這樣制作的framework只支持x86架構(gòu),因此4s不能運(yùn)行** 注意 :**cd 到.framework的路徑是不夠的,因?yàn)閮H僅是一個(gè)文件夾,真正的靜態(tài)庫是一個(gè)二進(jìn)制文件.因此查看架構(gòu)信息的時(shí)候需要跟這個(gè)靜態(tài)庫名字修改架構(gòu),使制作的framework支持所有架構(gòu)

5.png

靜調(diào)庫的合并與.a文件一樣,在此就不做贅述。至此SDK的開發(fā)就到此為止,真正的SDK開發(fā)需要在項(xiàng)目中一邊開發(fā)一邊調(diào)試

3 SDK靜調(diào)庫的調(diào)試

單獨(dú)進(jìn)行核心代碼SDK的開發(fā),開發(fā)完成以后需要拖到項(xiàng)目中調(diào)試,這樣是本末倒置的。SDK的開發(fā)需要在項(xiàng)目中調(diào)試以及開發(fā)。

6.png

創(chuàng)建完成以后,項(xiàng)目中的結(jié)構(gòu)發(fā)生變化,變化的位置已經(jīng)已經(jīng)圈出

7.png

在framework文件目錄下創(chuàng)建核心代碼類,并在項(xiàng)目中需要的地方import主頭文件,靜調(diào)庫的制作就不贅述了,與上面的一致。

4 制作靜態(tài)庫時(shí)注意的幾點(diǎn):

  1. 圖片資源的處理:兩種靜態(tài)庫,一般都是把圖片文件單獨(dú)的放在一個(gè).bundle文件中,一般.bundle的名字和.a或.framework的名字相同。.bundle文件很好弄,新建一個(gè)文件夾,把它改名為.bundle就可以了,右鍵,顯示包內(nèi)容可以向其中添加圖片資源。
  2. category是我們實(shí)際開發(fā)項(xiàng)目中經(jīng)常用到的,把category打成靜態(tài)庫是沒有問題的,但是在用這個(gè)靜態(tài)庫的工程中,調(diào)用category中的方法時(shí)會(huì)有找不到該方法的運(yùn)行時(shí)錯(cuò)誤(selector not recognized),解決辦法是:在使用靜態(tài)庫的工程中配置other linker flags的值為-ObjC -all_load
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容