iOS 靜態(tài)庫

一、靜態(tài)庫簡介

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

  • 1.2、根據源代碼的公開情況,庫可以分為2種類型

    • <1>、開源庫
      公開源代碼,能看到具體實現,比如我們常見的:AFNetworking、SDWebImage、MJRefresh 等等
    • <2>、閉源庫
      不公開源代碼,是經過編譯后的二進制文件,看不到具體實現
      主要分為:靜態(tài)庫、動態(tài)庫
  • 1.3、靜態(tài)庫和動態(tài)庫的存在形式

    • 靜態(tài)庫:.a.framework
    • 動態(tài)庫:.dylib.framework
  • 1.4、靜態(tài)庫和動態(tài)庫在使用上的區(qū)別

    • 靜態(tài)庫:鏈接時,靜態(tài)庫會被完整地復制到可執(zhí)行文件中,被多次使用就有多份冗余拷貝(如下圖所示)
      靜態(tài)庫
    • 動態(tài)庫:鏈接時不復制,程序運行時由系統動態(tài)加載到內存,供程序調用,系統只加載一次,多個程序共用,節(jié)省內存(如下圖所示)
      動態(tài)庫

      需要注意的是:iOS平臺 在 iOS8 之前,蘋果不允許第三方框架使用動態(tài)方式加載,從 iOS8 開始允許開發(fā)者有條件地創(chuàng)建和使用動態(tài)框架,這種框架叫做 Cocoa Touch Framework。雖然同樣是動態(tài)框架,但是和系統 framework 不同,app 中使用 Cocoa Touch Framework 制作的動態(tài)庫 在打包和提交 app 時會被放到 app main bundle 的根目錄 中,運行在沙盒里,而不是系統中。也就是說,不同的 app 就算使用了同樣的 framework,但還是會有多份的框架被分別簽名,打包和加載。不過 iOS8 上開放了 App Extension 功能,可以為一個應用創(chuàng)建插件,這樣主app和插件之間共享動態(tài)庫還是可行的。
      蘋果系統專屬的framework 是共享的(如UIKit), 但是我們自己使用 Cocoa Touch Framework 制作的動態(tài)庫是放到 app bundle 中,運行在沙盒中的

  • 1.5、 靜態(tài)庫應用場景?

    • 保護自己的核心代碼,比如國內的環(huán)信,百度地圖,高德地圖,友盟,個推,他們掌握有核心技術,同時是又希望更多的程序員來使用其技術,因此采用"閉源"的方式開發(fā)使用,你只能看到他們的.h文件以及一些不重要的.m文件
    • MRC 的項目,打包成靜態(tài)庫, 可以在ARC下直接使用, 不需要轉換
  • 1.6、靜態(tài)庫的特點?

    • .a.h 組成
    • 看不到具體實現的代碼

二、.a 靜態(tài)庫的制作

  • 2.1、 創(chuàng)建項目時, 直接選擇靜態(tài)庫(.a)

    創(chuàng)建項目時, 直接選擇靜態(tài)庫(`.a`)

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

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

  • 2.3、添加暴露的文件

    添加暴露的文件

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

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

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

  • 2.5、新建一個工程測試 上面我們創(chuàng)建的 .a 文件 與 暴露文件 是否可以使用

    新建一個工程測試 上面我們創(chuàng)建的 `.a` 文件 與 暴露文件 是否可以使用

    • 測試結果:

      • 1、使用6S模擬器進行測試, 可以使用
      • 2、使用低型號模擬器測試,; 失敗
      • 3、使用真機, 編譯; 失敗

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

    • 靜態(tài)庫所支持的架構
    • 模擬器: 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靜態(tài)庫 所支持的架構:

      cd 進入 .a靜態(tài)庫所在的文件夾
      lipo -info 庫文件名
      

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

      我們以上面在模擬器下的 `.a靜態(tài)庫` 為例

  • 2.6、怎樣一次編譯支持多個架構的的靜態(tài)庫?

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

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

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

    • 解決方案:xcodebuild 命令行生成靜態(tài)庫參考博客

      • debug(調試)版本

        xcodebuild -target 要生成的靜態(tài)庫目名 -configuration Debug -sdk iphoneos -arch armv7 -arch arm64
        xcodebuild -target 要生成的靜態(tài)庫目名 -configuration Debug -sdk iphonesimulator -arch i386 -arch x86_64
        
      • release(發(fā)布)版本

        xcodebuild -target 要生成的靜態(tài)庫目名 -configuration Release -sdk iphoneos -arch armv7 -arch arm64
        xcodebuild -target 要生成的靜態(tài)庫目名 -configuration Release -sdk iphonesimulator -arch i386 -arch x86_64
        
      • 提示:我們只需要生成發(fā)布版本的就好,如下步驟

        # 1、cd 進入靜態(tài)庫項目
        cd 靜態(tài)庫項目
        # 2、操作上面 release(發(fā)布)版本 的命令
        

        注意:在使用過 xcodebuild ,再利用 lipo -info 靜態(tài)庫名檢測,響應的架構都支持

  • 2.7、通過上面我們可以知道 .a靜態(tài)庫 在debug模式下的真機和模擬器編譯各會生成一個 .a靜態(tài)庫,在release模式下的真機和模擬器編譯也各會生成一個 .a靜態(tài)庫,那么我們給別人哪些 .a靜態(tài)庫用呢?
    答案是:給其他人在release模式下的:真機與模擬器下的.a靜態(tài)庫

    提示:.a靜態(tài)庫測試版本發(fā)布版本特點

    • Debug(調試版本):1、調試版本會包含完整的符號信息,以方便調試;2、調試版本不會對代碼進行優(yōu)化
    • Release(發(fā)布版本): 1、發(fā)布版本不會包含完整的符號信息;2、發(fā)布版本的執(zhí)行代碼是進行過優(yōu)化的;3、發(fā)布版本的大小會比調試版本的略小;4、在執(zhí)行速度方面,發(fā)布版本會更快些,但不意味著會有顯著的提升
  • 2.8、我們給用戶發(fā)布版本的兩個.a靜態(tài)庫(真機下的release模式下的.a靜態(tài)庫與模擬器release模式下的.a靜態(tài)庫),如果想要一個靜態(tài)庫, 既可以在模擬器上運行, 也可以在真機上運行怎么做?
    答案:把發(fā)布版本的兩個.a靜態(tài)庫合成一個 .a靜態(tài)庫??

    • 合并步驟:
      • <1>、檢查發(fā)布版本的兩個靜態(tài)庫是否支持的 架構都全


        檢查發(fā)布版本的兩個靜態(tài)庫是否支持的 架構都全
      • <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靜態(tài)庫的特點

        • (1)、合并.a好處,開發(fā)過程中既可以在真機上調試,也可以在模擬器上調試
        • (2)、 合并.a壞處,如果靜態(tài)庫太大,合并打包后,會非常大,因此很多第三方的靜態(tài)庫的.a是區(qū)分版本的

        提示:今后在使用.a靜態(tài)庫時一定注意版本

三、.framework 靜態(tài)庫的制作

  • 3.1、創(chuàng)建項目時, 直接選擇.framework靜態(tài)庫

    創(chuàng)建項目時, 直接選擇.framework靜態(tài)庫

  • 3.2、創(chuàng)建一個繼承于NSObjectJKTest類,并寫一個類方法,把該類的.h文件暴露出來

    創(chuàng)建一個繼承于`NSObject`的`JKTest`類,并寫一個類方法

    提示:記得把需要暴露的 .h 文件導入到在創(chuàng)建靜態(tài)庫的時候生成的 .h 文件里面,如上面的 JKOCProjectTool.h

    把該類的.h文件暴露出來
  • 3.3、利用上面2.6方案二生成發(fā)布版本的靜態(tài)庫,記得修改支持的最低版本,修改 把.framework的庫由動態(tài)庫改為靜態(tài)庫

    修改支持的最低版本

    修改 把`.framework`的庫由 動態(tài) 改為 靜態(tài)庫

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

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

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

    測試OK

  • 3.5、合并 .framework 靜態(tài)庫

    合并靜態(tài)庫

    lipo -create 真機的JKOCProjectTools路徑 模擬器的JKOCProjectTools路徑 -output 合并后的JKOCProjectTools文件
    

    切記:合成的是二進制文件而不是framework,最后合成的二進制文件替代之前的二進制文件即可

  • 3.6、補充:靜態(tài)庫操作

    • <1>、合成不同架構的庫(也就是上面的3.5)

      lipo -create xx xx -output xxx
      
    • <2>、分解合成庫

      lipo -thin 架構名稱 xx -output xx
      
    • <3>、測試靜態(tài)庫 所支持的架構

      cd 進入 靜態(tài)庫所在的文件夾
      lipo -info 庫文件名
      
    • <4>、從合成庫移除某個架構

      lipo -remove 架構名稱 xx -output xx
      

    提示:上面3.6中的 xx 代表靜態(tài)庫名

四、總結

  • 4.1、靜態(tài)庫打包的完整正確步驟

    • <1>、確定是靜態(tài)庫
      • .a 的肯定是靜態(tài)庫
      • .framework的需要設置鏈接類型,project -> Build Settings-> 搜索 Mach-o Type ; 改為靜態(tài)庫選擇 Static Library
        `.framework`的需要設置鏈接類型
    • <2>、確定支持模擬器或者真機中的所有架構
      • 如果使用的2.6類里面的 方案一 那就是xcode要支持所有的架構的模擬器,并且修改 Build Settings ->Build Active ->NO,這樣編譯之后,debug真機下支持debug真機下所有的架構,debug模擬器下支持debug模擬器下所有的架構
      • 如果使用的2.6類里面的 方案二 xcodebuild方法就可以支持所有的架構
    • <3>、提供的靜態(tài)庫應該是 release版本
      • 如果使用的2.6類里面的 方案一:項目 -> Edit Scheme -> Run -> Release/Debug 分別進行編譯
      • 如果使用的2.6類里面的 方案二 xcodebuild方法,在命令類里面輸入 Release 就好
  • 4.2、.a靜態(tài)庫.framework靜態(tài)庫的區(qū)別?

    • <1>、.a 是一個純二進制文件, .framework中除了有二進制文件之外還有資源文件,.bundle就是資源文件
    • <2>、.a 文件不能直接使用, 至少要有.h文件的配合; .framework 文件可以直接使用
    • <3>、.a + .h + sourceFile = .framework
    • <4>、建議使用 .framework
  • 4.3、靜態(tài)庫開發(fā)中的常見問題

    • 問題1: 有些第三方庫會使用到一些圖片素材,例如公司的logo,xib文件等,如何做?
      答:創(chuàng)建一個.bundle文件,創(chuàng)建方式看 資源文件 .buldle 的添加第十。
    • 問題2: 如果用戶需要導入的頭文件過多怎么加?
      答:在創(chuàng)建 .framework項目會默認生成一個 .h 文件,我們可以把其他的 .h 文件導入 默認生成一個.h 文件 中
    • 問題3: 靜態(tài)庫程序怎樣測試?
      答:創(chuàng)建一個創(chuàng)建復合項目,看下面 4.4 創(chuàng)建的步驟
  • 4.4、創(chuàng)建一個創(chuàng)建復合項目(符合工程的名字定義為:復合項目

    • <1>、在復合項目中添加一個.framework的靜態(tài)庫JKTools

      在復合項目中添加一個`.framework`的靜態(tài)庫`JKTools`

    • <2>、創(chuàng)建一個JKTest類,創(chuàng)建一個類方法,并把JKTest的.h放到創(chuàng)建靜態(tài)庫生成的.h文件里面

      創(chuàng)建一個`JKTest`類,創(chuàng)建一個類方法

      把JKTest的`.h`放到創(chuàng)建靜態(tài)庫生成的`.h`文件里面

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

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

      設置為靜態(tài)庫

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

      把需要暴露的文件放到Public里面

    • <4>、在復合項目添加我們的靜態(tài)庫依賴


      在符合項目添加我們的靜態(tài)庫依賴
    • <5>、測試
      導入#import <JKTools/JKTools.h>,調用下面的方法

      [JKTest jk_test];
      

      打印結果:

      復合項目的測試
      
    • <6>、有關 .framework的文件導出,我就不再重復了,也就是上面2.6的步驟,有關合上面也有講述

五、將MRC的項目,打包成靜態(tài)庫, 可以在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下的類打包成靜態(tài)庫,.a 或者 .framework 都可以,下面以打包成.framework為例,步驟如下

    • <1>、創(chuàng)建一個.framework項目,這里名字一JKTools為例,把上面JKTools.hJKTools.m拖進去,把并修改項目為 MRC
      修改項目為MRC

      TARGETS->Build Settings下搜 Automatic Reference ,改為 NO;其中YES為ARC,NO為MRC。
    • <2>、重復 4.4 里面 <3> 的步驟
    • <3>、生成發(fā)布版本的靜態(tài)庫以及合并真機與模擬器的二進制文件,最后把合并的二進制文件替換掉 真機下framework里面的二進制文件
    • <4>、把framework拖入 ARC的項目,直接導入framework里面的.h文件查看是否可以,經過測試時OK的,不懂的你可以聯系我

    五、Swift打包動態(tài)庫

    • 5.1、創(chuàng)建一個Swift 下的 .framework 工程,命名為 JKTools ,同時創(chuàng)建一個類JKTest,寫一個方法 jk_test

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

    • 5.2、把支持的最低版本調為 9.0,具體的看自己項目


      把支持的最低版本調為 9.0,具體的看自己項目
    • 5.3、修改 Build Settings ->Build Active ->NO,這樣編譯之后,debug真機下支持debug真機下所有的架構,debug模擬器下支持debug模擬器下所有的架構

    • 5.4、修改 為靜態(tài)庫


      修改 為靜態(tài)庫
    • 5.5、在release下編譯模擬器與真機,生成像一個的.framework 文件,把類里面的二進制文件合并成一個,步驟和上面一樣,不再重復了

    • 5.6、測試靜態(tài)庫的使用,結果顯示是OK的


      測試靜態(tài)庫的使用,結果顯示是OK的

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

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

友情鏈接更多精彩內容