歡迎光臨
每天分享高質量文章

iOS 靜態庫

作者:IIronMan

鏈接:https://www.jianshu.com/p/d79f6c866fdb

一、靜態庫簡介

1.1、庫:是程式代碼的集合,是共享程式代碼的一種方式。

 

1.2、根據原始碼的公開情況,庫可以分為2種型別

 

  • <1>、開源庫

    公開原始碼,能看到具體實現,比如我們常見的:AFNetworking、SDWebImage、MJRefresh 等等

  • <2>、閉源庫

    不公開原始碼,是經過編譯後的二進制檔案,看不到具體實現

 

主要分為:靜態庫、動態庫

 

1.3、靜態庫和動態庫的存在形式

 

  • 靜態庫:.a 和 .framework

  • 動態庫:.dylib 和 .framework

 

1.4、靜態庫和動態庫在使用上的區別

 

  • 靜態庫:鏈接時,靜態庫會被完整地複製到可執行檔案中,被多次使用就有多份冗餘拷貝(如下圖所示)

 

 

  • 動態庫:鏈接時不複製,程式運行時由系統動態加載到記憶體,供程式呼叫,系統只加載一次,多個程式共用,節省記憶體(如下圖所示)

 

 

需要註意的是:專案中如果使用了自製的動態庫,不能被上傳到AppStore, 不允許上架!

 

1.5、 靜態庫應用場景?

 

  • 保護自己的核心代碼,比如國內的環信,百度地圖,高德地圖,友盟,個推,他們掌握有核心技術,同時是又希望更多的程式員來使用其技術,因此採用”閉源”的方式開發使用,你只能看到他們的.h檔案以及一些不重要的.m檔案

  • 將 MRC 的專案,打包成靜態庫, 可以在ARC下直接使用, 不需要轉換

 

1.6、靜態庫的特點?

 

  • 由 .a 和 .h 組成

  • 看不到具體實現的代碼

二、.a 靜態庫的製作

2.1、 創建專案時, 直接選擇靜態庫(.a)

 

 

創建專案時, 直接選擇靜態庫(`.a`)

 

2.2、定義一個類方法+(void)jk_test,在.h裡面暴露出來jk_test

 

 

定義一個類方法`+(void)jk_test`

 

2.3、添加暴露的檔案

 

 

添加暴露的檔案

 

2.4、分別在真機與6s下編譯,查看生成的.a與暴露檔案

 

 

分別在真機與6s下編譯,查看生成的.a與暴露檔案

 

 

分別在真機與6s下編譯,查看生成的.a與暴露檔案

 

2.5、新建一個工程測試 上面我們創建的 .a 檔案 與 暴露檔案 是否可以使用

 

 

新建一個工程測試 上面我們創建的 `.a` 檔案 與 暴露檔案 是否可以使用

 

測試結果:

 

1、使用6S模擬器進行測試, 可以使用

2、使用低型號模擬器測試,; 失敗

3、使用真機, 編譯; 失敗

 

分析原因:原因是靜態庫分架構,不同的CPU架構是不一樣的 ,如果 .a靜態庫 不支持架構,運行會報錯

靜態庫所支持的架構

模擬器: 4s~5  : i386;5s ~ XS Max: x86_64

真機: 3gs~4s : armv7;5/5c : armv7s(armv7兼容armv7s);5s~XS Max: arm64: arm64

提示:上面的 i386、x86_64、armv7、armv7s、arm64 都是架構的名字

 

測試 .a靜態庫 所支持的架構:

 

cd 進入 .a靜態庫所在的檔案夾
lipo -info 庫檔案

我們以上面在模擬器下的 .a靜態庫 為例,如下圖

 

 

我們以上面在模擬器下的 `.a靜態庫` 為例

 

2.6、怎樣一次編譯支持多個架構的的靜態庫?

 

解決方案一:在 Build Settings ->Build Active ->NO,這樣設置之後,debug真機下支持debug真機下所有的架構,debug模擬器下支持debug模擬器下所有的架構,再重覆上面的測試,在iPhone5或者iPhone4下就不會報錯了

 

 

在 `Build Settings` ->` Build Active` ->` NO`

 

註意:你的xcode要有上面架構的機型,否則只會包含有的架構,如果沒有 i386架構,你可以 下載 4s~5 模擬器,再重覆上面的操作

 

解決方案二:xcodebuild 命令列生成靜態庫參考博客

 

debug(除錯)版本

 

xcodebuild -target 要生成的靜態庫目名 -configuration Debug -sdk iphoneos -arch armv7 -arch arm64
xcodebuild -target 要生成的靜態庫目名 -configuration Debug -sdk iphonesimulator -arch i386 -arch x86_64

release(發佈)版本

xcodebuild -target 要生成的靜態庫目名 -configuration Release -sdk iphoneos -arch armv7 -arch arm64
xcodebuild -target 要生成的靜態庫目名 -configuration Release -sdk iphonesimulator -arch i386 -arch x86_64

提示:我們只需要生成發佈版本的就好,如下步驟

# 1、cd 進入靜態庫專案
cd 靜態庫專案
# 2、操作上面 release(發佈)版本 的命令

註意:在使用過 xcodebuild ,再利用 lipo -info 靜態庫名檢測,響應的架構都支持

 

2.7、通過上面我們可以知道 .a靜態庫 在debug樣式下的真機和模擬器編譯各會生成一個 .a靜態庫,在release樣式下的真機和模擬器編譯也各會生成一個 .a靜態庫,那麼我們給別人哪些 .a靜態庫用呢?

 

答案是:給其他人在release樣式下的:真機與模擬器下的.a靜態庫

 

提示:.a靜態庫 在 測試版本 與 發佈版本 的特點

  • Debug(除錯版本):1、除錯版本會包含完整的符號信息,以方便除錯;2、除錯版本不會對代碼進行優化

  • Release(發佈版本): 1、發佈版本不會包含完整的符號信息;2、發佈版本的執行代碼是進行過優化的;3、發佈版本的大小會比除錯版本的略小;4、在執行速度方面,發佈版本會更快些,但不意味著會有顯著的提升

 

2.8、我們給用戶發佈版本的兩個.a靜態庫(真機下的release樣式下的.a靜態庫與模擬器release樣式下的.a靜態庫),如果想要一個靜態庫, 既可以在模擬器上運行, 也可以在真機上運行怎麼做?

 

答案:把發佈版本的兩個.a靜態庫合成一個 .a靜態庫

 

合併步驟:

 

<1>、檢查發佈版本的兩個靜態庫是否支持的 架構都全

 

 

檢查發佈版本的兩個靜態庫是否支持的 架構都全

 

<2>、合併 .a

 

 

合併 `.a`

cd 進入 Products 檔案夾
lipo -create  Release-iphoneos/libJKOCProjectTool.a  Release-iphonesimulator/libJKOCProjectTool.a  -output NewJKOCProjectTool.a

提示:NewJKOCProjectTool.a 是生成的新的 .a,合成的.a的大小是合成前兩個.a大小的和

 

<3>、合成後的.a靜態庫的特點

 

(1)、合併.a的好處,開發過程中既可以在真機上除錯,也可以在模擬器上除錯

(2)、 合併.a的壞處,如果靜態庫太大,合併打包後,會非常大,因此很多第三方的靜態庫的.a是區分版本的

 

提示:今後在使用.a靜態庫時一定註意版本

三、.framework 靜態庫的製作

3.1、創建專案時, 直接選擇.framework靜態庫

 

 

創建專案時, 直接選擇.framework靜態庫

 

3.2、創建一個繼承於NSObject的JKTest類,並寫一個類方法,把該類的.h檔案暴露出來

 

 

創建一個繼承於`NSObject`的`JKTest`類,並寫一個類方法

 

 

把該類的.h檔案暴露出來

 

3.3、利用上面2.6的方案二生成發佈版本的靜態庫,記得修改支持的最低版本,修改 把.framework的庫由動態庫改為靜態庫

 

 

修改支持的最低版本

 

 

修改 把`.framework`的庫由 動態 改為 靜態庫 

// 1.cd 進入靜態庫專案
cd JKOCProjectTool
// 2.使用xcodebuild生成靜Release下真機的靜態庫
xcodebuild -target JKOCProjectTool -configuration Release -sdk iphoneos -arch armv7 -arch arm64
// 3.使用xcodebuild生成靜Release下模擬器的靜態庫
xcodebuild -target JKOCProjectTool -configuration Release -sdk iphonesimulator -arch i386 -arch x86_64

 

使用xcodebuild生成靜Release下模擬器的靜態庫

 

提示:你如果需要 Debug 下的靜態庫,參照 2.6 自行生成

 

3.4、測試一下是否可以運行(提示:如果不把動態庫改為靜態庫會運行報錯,如果你想強行使用動態庫,那麼你就在:TARGETS->General->Embedded Binaries 添加你的庫)

 

 

測試OK

 

3.5、合併 .framework 靜態庫

 

 

合併靜態庫

lipo -create 真機的JKOCProjectTools路徑 模擬器的JKOCProjectTools路徑 -output 合併後的JKOCProjectTools檔案

切記:合成的是二進制檔案而不是framework,最後合成的二進制檔案替代之前的二進制檔案即可

四、總結

4.1、靜態庫打包的完整正確步驟

 

<1>、確定是靜態庫

 

.a 的肯定是靜態庫

 

.framework的需要設置鏈接型別,project -> Build Settings-> 搜索 Mach-o Type ; 改為靜態庫選擇 Static Library

 

 

`.framework`的需要設置鏈接型別

 

<2>、確定支持模擬器或者真機中的所有架構

  • 如果使用的2.6類裡面的 方案一 那就是xcode要支持所有的架構的模擬器,並且修改 Build Settings ->Build Active ->NO,這樣編譯之後,debug真機下支持debug真機下所有的架構,debug模擬器下支持debug模擬器下所有的架構

  • 如果使用的2.6類裡面的 方案二 xcodebuild方法就可以支持所有的架構

 

<3>、提供的靜態庫應該是 release版本

  • 如果使用的2.6類裡面的 方案一:專案 -> Edit Scheme -> Run -> Release/Debug 分別進行編譯

  • 如果使用的2.6類裡面的 方案二 xcodebuild方法,在命令類裡面輸入 Release 就好

 

4.2、.a靜態庫和.framework靜態庫的區別?

 

<1>、.a 是一個純二進制檔案,  .framework中除了有二進制檔案之外還有資源檔案,.bundle就是資源檔案

<2>、.a 檔案不能直接使用, 至少要有.h檔案的配合; .framework 檔案可以直接使用

<3>、.a + .h + sourceFile = .framework

<4>、建議使用 .framework

 

4.3、靜態庫開發中的常見問題

 

問題1: 有些第三方庫會使用到一些圖片素材,例如公司的logo,xib檔案等,如何做?

答:創建一個.bundle檔案,創建方式看 資源檔案 .buldle 的添加第十。

 

問題2: 如果用戶需要匯入的頭檔案過多怎麼加?

答:在創建  .framework專案會預設生成一個 .h 檔案,我們可以把其他的 .h 檔案匯入 預設生成一個.h 檔案 中

 

問題3: 靜態庫程式怎樣測試?

答:創建一個創建複合專案,看下麵 4.4 創建的步驟

 

4.4、創建一個創建複合專案(符合工程的名字定義為:複合專案)

 

<1>、在複合專案中添加一個.framework的靜態庫JKTools

 

 

在複合專案中添加一個`.framework`的靜態庫`JKTools`

 

<2>、創建一個JKTest類,創建一個類方法,並把JKTest的.h放到創建靜態庫生成的.h檔案裡面

 

 

創建一個`JKTest`類,創建一個類方法

 

 

把JKTest的`.h`放到創建靜態庫生成的`.h`檔案裡面

 

<3>、選中JKTools,修改下麵選項

 

 

修改JKTools支持的最低版本為9.0,看自己專案了

 

 

設置為靜態庫

 

 

修改 Build Settings ->Build Active ->NO,這樣編譯之後,debug真機下支持debug真機下所有的架構,debug模擬器下支持debug模擬器下所有的架構

 

 

把需要暴露的檔案放到Public裡面

 

<4>、在符合專案添加我們的靜態庫依賴

 

 

在符合專案添加我們的靜態庫依賴

 

<5>、測試

 

匯入#import,呼叫下麵的方法

[JKTest jk_test];

打印結果:

複合專案的測試

<6>、有關 .framework的檔案匯出,我就不再重覆了,也就是上面2.6的步驟,有關合上面也有講述

五、將MRC的專案,打包成靜態庫, 可以在ARC下直接使用, 不需要轉換

5.1、應用場景

 

你找到一個功能是ARC專案下的,你想用,裡面有很多的類,你怎麼把他們搬到ARC專案下使用???

 

5.2、解決方案一(適用於類不太的情況)

 

<1>、我們模擬一個類JKTools,它是MRC下的專案

 

 

我們模擬一個類JKTools,它是MRC下的專案

 

<2>、我們把JKTools的.h與.m拖到ARC的工程下,報錯是肯定的,我們看下如何處理。如下圖

 

 

在ARC圖中路徑找到MRC下的.m檔案,雙擊輸入-fno-objc-arc

 

提示:在ARC圖中路徑找到MRC下的.m檔案,雙擊輸入-fno-objc-arc,再運行就不會報錯了

 

5.3、解決方案二(適用於MRC的類很多的情況):把MRC下的類打包成靜態庫,.a 或者 .framework 都可以,下麵以打包成.framework為例,步驟如下

 

<1>、創建一個.framework專案,這裡名字一JKTools為例,把上面JKTools.h和JKTools.m拖進去,把並修改專案為 MRC

 

 

修改專案為MRC

 

在TARGETS->Build Settings下搜 Automatic Reference ,改為 NO;其中YES為ARC,NO為MRC。

 

<2>、重覆 4.4 裡面<3>的步驟

 

<3>、生成發佈版本的靜態庫以及合併真機與模擬器的二進制檔案,最後把合併的二進制檔案替換掉 真機下framework裡面的二進制檔案

 

<4>、把framework拖入 ARC的專案,直接匯入framework裡面的.h檔案查看是否可以,經過測試時OK的,不懂的你可以聯繫我

六、Swift打包動態庫

6.1、創建一個Swift 下的 .framework 工程,命名為 JKTools ,同時創建一個類JKTest,寫一個方法 jk_test

 

 

創建一個`Swift` 下的 `.framework` 工程,命名為 `JKTools` ,同時創建一個類`JKTest`,寫一個方法 `jk_test`

 

6.2、把支持的最低版本調為 9.0,具體的看自己專案

 

 

把支持的最低版本調為 9.0,具體的看自己專案

 

6.3、修改 Build Settings ->Build Active ->NO,這樣編譯之後,debug真機下支持debug真機下所有的架構,debug模擬器下支持debug模擬器下所有的架構

 

6.4、修改 為靜態庫

 

 

修改 為靜態庫

 

6.5、在release下編譯模擬器與真機,生成像一個的.framework 檔案,把類裡面的二進制檔案合併成一個,步驟和上面一樣,不再重覆了

 

6.6、測試靜態庫的使用,結果顯示是OK的

 

 

測試靜態庫的使用,結果顯示是OK的

 

到此,靜態庫的相關知識記錄到這,相比較其他的博客還是比較詳細的。遇到任何問題都可以再我的個人信息裡面來聯繫我。

 


編號390,輸入編號直達本文

●輸入m獲取文章目錄

推薦↓↓↓

 

程式員求職面試

更多推薦25個技術類微信公眾號

涵蓋:程式人生、演算法與資料結構、黑客技術與網絡安全、大資料技術、前端開發、Java、Python、Web開發、安卓開發、iOS開發、C/C++、.NET、Linux、資料庫、運維等。

赞(0)

分享創造快樂