使用framework打包靜態(tài)庫

1、認識靜態(tài)庫和動態(tài)庫

首先 是對程序代碼、函數(shù)及資源文件的封裝,是一種共享程序代碼,實現(xiàn)代碼資源復用的方式。分為 靜態(tài)庫動態(tài)庫

靜態(tài)庫和動態(tài)庫最明顯的區(qū)別在于載入鏈接時期的不同,是相對于編譯期和運行期而言的。

靜態(tài)庫 在程序編譯時被鏈接到目標代碼塊,模塊化提高代碼的復用性,多次使用將多次拷貝,容易造成冗余,使得包變大。

動態(tài)庫 在程序編譯時不會被鏈接,而是在程序運行時才被動態(tài)載入加到內(nèi)存中,系統(tǒng)只需要加載一次,供多個程序共享使用,共享代碼節(jié)省內(nèi)存空間。由于運行時動態(tài)載入的特性,我們可隨時對庫進行更新,而不需要重新編譯代碼,實現(xiàn) 動態(tài)更新 。但是可能會導致運行時錯誤且不易于定位和修復。

iOS8之前蘋果不允許第三方框架使用動態(tài)方式加載,iOS8之后新增APP Extension,主APP需要和Extension共享代碼;緊接著Swift語言機制不支持靜態(tài)庫(因為Swift運行庫沒被包含在iOS系統(tǒng)中而是打包進APP中,靜態(tài)庫會導致最終的目標程序中包含重復的運行庫),于是推出 framework ,framework 既可以打包靜態(tài)庫又可以打包動態(tài)庫。本文著重介紹如何使用framework打包靜態(tài)庫。有關(guān)靜態(tài)庫和動態(tài)庫的知識可以自行深入學習,這里只做簡單介紹。

2、封裝framework靜態(tài)庫

  • 創(chuàng)建framework
  • 配置 Build Setting

修改 Mach-O TypeStatic Library,將鏈接時生成的執(zhí)行文件類型設(shè)置成靜態(tài)庫類型
設(shè)置 Dead Code StrippingYES 死碼(代碼被定義卻從未被調(diào)用)剝離,去掉不會執(zhí)行到的冗余代碼,為編譯包瘦身

設(shè)置 Build Active Architecture OnlyNO 包含支持多種架構(gòu),否則為僅支持當前活躍架構(gòu)的模擬器或真機。 Valid Architectures 可控制支持的架構(gòu),如舍棄 armv7 ,則不支持 4s 及以往機型,為打包瘦身。

真機(armv7=3gs-4s,armv7s=5-5c, arm64=5s-)
模擬器(i386=3gs-5,x86_64=5s-)

設(shè)置 framework 支持的最低版本

  • 將 xib 、圖像資源包含到 framework 中,將需要暴露的 .h 文件放在 Public 中,需要編譯的 .m 文件放在 Compile Sources,并在建立 framework 時自動生成的頭文件中加入要 暴露的頭文件.h ,否則會報 Warning
  • 開始編譯

選中真機/模擬器,Command+B 編譯,分別生成只支持真機/模擬器的靜態(tài)庫,對.framework 右鍵 Show In Finder 可找到對應(yīng)的靜態(tài)庫

3、制作通用靜態(tài)庫

有兩種方法可合并上述生成的只支持真機、模擬器版本的靜態(tài)庫為通用庫

  1. 使用終端輸入命令行語句

lipo -create (此處填寫真機 FrameworkDemo 文件路徑) (此處填寫模擬器 FrameworkDemo 文件路徑) -output 自定義合成文件存儲路徑(合成文件的名字 FrameworkDemo ),生成合并后的 FrameworkDemo 文件,將此文件拷貝到相應(yīng)的 FrameworkDemo.framework 中替換即可。

  1. 使用 Aggregate
  • 創(chuàng)建 Aggregate
  • 編寫自定義 shell 腳本,選擇當前 target,Command+B 編譯
    # define output folder environment variable
    
    UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal
    
    # make sure the output directory exists
    
    mkdir -p "${UNIVERSAL_OUTPUTFOLDER}"
    
    #  copy the header file to universal dir,make sure your "${CONFIGURATION}-iphoneos/usr" dir exists
    
    cp -R "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework" "${UNIVERSAL_OUTPUTFOLDER}/"
    
    #  Create universal binary file using lipo
    
    lipo -create "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework/${PROJECT_NAME}"    "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/${PROJECT_NAME}" -output "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/${PROJECT_NAME}"
    
    open "${UNIVERSAL_OUTPUTFOLDER}"

打開終端進入到對應(yīng)目錄查看靜態(tài)庫信息,使用 lipo -info 指令

我們便可直接使用 Debug-universal 里面合并后的通用版本 framework 了。以上打包的是 debug 模式,若想發(fā)布可打包成 release 模式,只需在 Edit Scheme 里設(shè)置即可。支持 `framework 靜態(tài)庫打包完畢。。

4、問題

  • 當靜態(tài)庫中包含 Category 的時候,會報錯,原因是跟 OC 的 runtime 機制有關(guān)。Objective-C 沒有為每個函數(shù)、方法定義鏈接符號,它只為每個類創(chuàng)建鏈接符號。所以當我們在靜態(tài)庫中使用類別來擴展已有類的時候,鏈接器不知道如何把類原有的方法和類別中的方法整合起來,就會導致你調(diào)用類別中的方法時,出現(xiàn)”selector not recognized”,也就是找不到方法定義的錯誤。為了解決這個問題,引入了可以給鏈接器添加 -ObjC 標志,它的作用就是將靜態(tài)庫中所有的和對象相關(guān)的文件都加載進來。

  • 靜態(tài)庫中如果包含 xib 、圖片等資源,使用 NSBundle 讀取需注意資源路徑,例如

self = [[[NSBundle mainBundle]  loadNibNamed:@"xxxx.framewrok/TestView"  owner:nil options:nil] lastObject] ;
img.image = [UIImage imageNamed:@"xxxx.framewrok/test.png"];

完結(jié)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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