作者: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、資料庫、運維等。