1. 程式人生 > >封裝.a檔案以及應用.a檔案

封裝.a檔案以及應用.a檔案

2016/4/7

簡介

什麼是庫?

庫是程式程式碼的集合,是共享程式程式碼的一種方式

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

開源庫

公開原始碼,能看到具體實現

比如 SDWebImage 、 AFNetworking

閉源庫

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

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

靜態庫和動態庫

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

靜態庫: .a 和 .framework

動態庫: .dylib 和 .framework

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

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

動態庫:連結時不復制,程式執行時由系統動態載入到記憶體,供程式呼叫,系統只加載一次,多個程式共用,節省記憶體 (右圖所示)

需要注意的是:

專案中如果使用了自制的動態庫,不能被上傳到 AppStore

製作 .a

新建專案-> 選擇 “Cocoa Touch Static Library”


新增庫需要包含的原始碼


選擇需要暴露出來的 .h 檔案, .m 檔案會自動編譯到 .a 檔案中


選擇真機裝置,然後 Command+B 編譯, libFYSView.a 檔案從紅色變為黑色,這個地方要詳細說明一下操作步驟。目前很多教程建立的.a靜態庫是不支援i386等平臺的。(支援平臺型別的命令在下面會給出)

首先要點選工程 選擇Edit Scheme 步驟如下圖


右擊 “Show In Finder” ,檢視製作好的 .a 檔案

  • Release-iphoneos 資料夾裡面的東西是用在真機上的

  • Release-iphonesimulator 資料夾裡面的東西是用在模擬器上的

  • 如果 Scheme 是 Debug 模式,生成的資料夾就以 Debug 開頭

如果想讓一個 .a 檔案能同時用在真機和模擬器上,需要進行合併

在終端輸入指令

找到對應的檔案,先cd這個資料夾,

cd /Users/dianshiuser/Library/Developer/Xcode/DerivedData/FYSFlashLabel-heypxodtjyktblbfxqauguwfsnsk/Build/Products/Release-iphonesimulator

然後執行如下操作:

lipo -create Release-iphoneos/libFYSFlashLabel.a Release-iphonesimulator/libFYSFlashLabel.a -output libFlashLabelSDK.a

.a 檔案的體積(一般情況下)

  • 真機用的 .a > 模擬器用的 .a

  • 所合成 .a == 真機用的 .a + 模擬器用的 .a

通過 lipo –info libFlashLabelSDK.a 可以檢視 .a 的型別(模擬器還是真機)

我這個是合併後的靜態庫檔案,所以支援i386、x86_64、arm64、armv7型別

armv7是支援比iphone5舊的那些裝置,armv7s是iphone5或ipad4或者以後的新裝置,i386是模擬器的。arm64是iPhone5s

使用 .a

如何使用 .a

直接將 .a 、 .h 、資原始檔拖拽到其他專案中即可


我把FYS_Header和FYSView合併在SDK的.h檔案,方便呼叫。因為FYS_Header需要在多個地方應用,之前封裝的.a檔案不能正常訪問所以就這樣做了。
在使用自制的靜態庫時,如果遇到error:unrecognized selector sent to class這樣的錯誤,檢視Other Linker Flags,有沒有設定Other Linker Flags設定的三個值:-all_load就是會載入靜態庫檔案中的所有成員,-ObjC就是會載入靜態庫檔案中實現一個類或者分類的所有成員,-force_load(包的路徑)就是會載入指定路徑的靜態庫檔案中的所有成員。所以對於使用runtime時候的反射呼叫的方法應該使用這三個中的一個進行link,以保證所有的類都可以載入到記憶體中供程式動態呼叫
出錯原因:應為.a檔案中有category檔案,所以Xcode編譯就把category中的方法錯誤認為是系統的內部方法,但系統中沒有這個方法,所以除錯的時候,就找不到該方法的實現,報出錯誤資訊:'unrecognized selector sent to class *******'

部分援引:http://www.cocoachina.com/ios/20150226/11182.html

2016/4/8更新
當應用別人的.a庫,只能在單一平臺上執行時,你可以把sdk的介面都實現一個空函式然後編譯一個模擬器版本或是真機版本然後合併版本就好了。(藍芽功能的開發,因為藍芽只能在真機上除錯,所以有的SDK只支援真機)

2016/4/14更新
因為之前的教程生成靜調庫不支援i386等平臺型別,現更新一下生成的支援i386等平臺型別的靜態庫教程。