iOS 靜態(tài)庫

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

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

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

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

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

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

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

  • 1.5、 靜態(tài)庫應(yīng)用場(chǎng)景?

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

    • .a.h 組成
    • 看不到具體實(shí)現(xiàn)的代碼

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

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

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

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

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

  • 2.3、添加暴露的文件

    添加暴露的文件

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

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

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

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

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

    • 測(cè)試結(jié)果:

      • 1、使用6S模擬器進(jìn)行測(cè)試, 可以使用
      • 2、使用低型號(hào)模擬器測(cè)試,; 失敗
      • 3、使用真機(jī), 編譯; 失敗

    分析原因:原因是靜態(tài)庫分架構(gòu),不同的CPU架構(gòu)是不一樣的 ,如果 .a靜態(tài)庫 不支持架構(gòu),運(yùn)行會(huì)報(bào)錯(cuò)

    • 靜態(tài)庫所支持的架構(gòu)
    • 模擬器: 4s~5 : i386;5s ~ XS Max: x86_64
    • 真機(jī): 3gs~4s : armv7;5/5c : armv7s(armv7兼容armv7s);5s~XS Max: arm64: arm64
      提示:上面的 i386、x86_64、armv7、armv7s、arm64 都是架構(gòu)的名字
    • 測(cè)試 .a靜態(tài)庫 所支持的架構(gòu):

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

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

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

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

    • 解決方案:在 Build Settings ->Build Active ->NO,這樣設(shè)置之后,debug真機(jī)下支持debug真機(jī)下所有的架構(gòu),debug模擬器下支持debug模擬器下所有的架構(gòu),再重復(fù)上面的測(cè)試,在iPhone5或者iPhone4下就不會(huì)報(bào)錯(cuò)了

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

      注意:你的xcode要有上面架構(gòu)的機(jī)型,否則只會(huì)包含有的架構(gòu),如果沒有 i386架構(gòu),你可以 下載 4s~5 模擬器,再重復(fù)上面的操作

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

      • debug(調(diào)試)版本

        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 進(jìn)入靜態(tài)庫項(xiàng)目
        cd 靜態(tài)庫項(xiàng)目
        # 2、操作上面 release(發(fā)布)版本 的命令
        

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

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

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

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

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


        檢查發(fā)布版本的兩個(gè)靜態(tài)庫是否支持的 架構(gòu)都全
      • <2>、合并 .a

        合并 `.a`

        cd 進(jìn)入 Products 文件夾
        lipo -create  Release-iphoneos/libJKOCProjectTool.a  Release-iphonesimulator/libJKOCProjectTool.a  -output NewJKOCProjectTool.a
        

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

      • <3>、合成后的.a靜態(tài)庫的特點(diǎn)

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

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

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

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

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

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

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

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

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

    修改支持的最低版本

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

    // 1.cd 進(jìn)入靜態(tài)庫項(xiàng)目
    cd JKOCProjectTool
    // 2.使用xcodebuild生成靜Release下真機(jī)的靜態(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、測(cè)試一下是否可以運(yùn)行(提示:如果不把動(dòng)態(tài)庫改為靜態(tài)庫會(huì)運(yùn)行報(bào)錯(cuò),如果你想強(qiáng)行使用動(dòng)態(tài)庫,那么你就在:TARGETS->General->Embedded Binaries 添加你的庫)

    測(cè)試OK

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

    合并靜態(tài)庫

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

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

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

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

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

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

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

      lipo -remove 架構(gòu)名稱 xx -output xx
      

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

四、總結(jié)

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

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

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

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

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

      在復(fù)合項(xiàng)目中添加一個(gè)`.framework`的靜態(tài)庫`JKTools`

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

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

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

    • <3>、選中JKTools,修改下面選項(xiàng)

      修改JKTools支持的最低版本為9.0,看自己項(xiàng)目了

      設(shè)置為靜態(tài)庫

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

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

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


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

      [JKTest jk_test];
      

      打印結(jié)果:

      復(fù)合項(xiàng)目的測(cè)試
      
    • <6>、有關(guān) .framework的文件導(dǎo)出,我就不再重復(fù)了,也就是上面2.6的步驟,有關(guān)合上面也有講述

五、將MRC的項(xiàng)目,打包成靜態(tài)庫, 可以在ARC下直接使用, 不需要轉(zhuǎn)換

  • 5.1、應(yīng)用場(chǎng)景
    你找到一個(gè)功能是ARC項(xiàng)目下的,你想用,里面有很多的類,你怎么把他們搬到ARC項(xiàng)目下使用???

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

    • <1>、我們模擬一個(gè)類JKTools,它是MRC下的項(xiàng)目


      我們模擬一個(gè)類JKTools,它是MRC下的項(xiàng)目
    • <2>、我們把JKTools的.h與.m拖到ARC的工程下,報(bào)錯(cuò)是肯定的,我們看下如何處理。如下圖


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

    提示:在ARC圖中路徑找到MRC下的.m文件,雙擊輸入-fno-objc-arc,再運(yùn)行就不會(huì)報(bào)錯(cuò)了

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

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

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

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

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

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

    • 5.2、把支持的最低版本調(diào)為 9.0,具體的看自己項(xiàng)目


      把支持的最低版本調(diào)為 9.0,具體的看自己項(xiàng)目
    • 5.3、修改 Build Settings ->Build Active ->NO,這樣編譯之后,debug真機(jī)下支持debug真機(jī)下所有的架構(gòu),debug模擬器下支持debug模擬器下所有的架構(gòu)

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


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

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


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

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。