【轉】 iOS 開發之靜態庫.a和動態庫詳解 -- 不錯

原文網址:http://blog.csdn.net/lxl_815520/article/details/52154331ios

一, 簡單介紹

1.什麼是庫

 庫是程序代碼的集合,是共享程序代碼的一種方式架構

 根據源代碼的公開狀況,庫能夠分爲 2 種類型框架

   * 開源庫iphone

     公開源代碼,能看到具體實現工具

     好比 SDWebImage 、 AFNetworking性能

   * 閉源庫測試

     不公開源代碼,是通過編譯後的二進制文件,看不到具體實現優化

     好比 靜態庫 、動態庫網站

2.關於靜態庫和動態庫

    1>靜態庫和動態庫的存在形式ui

       *  靜態庫: .a 和 .framework

       *  動態庫: .dylib 和 .framework

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

       *  靜態庫:連接時,靜態庫會被完整地複製到可執行文件中, 被屢次使用就有多份冗餘拷貝

       *  動態庫:連接時不復制,程序運行時由系統動態加載到內存,供程序調用,系統只加載一次(共享),多個程序共用,節省內存

    注意:* 項目中若是使用了自制的動態庫,不能被上傳到 AppStore. 

           * 系統直接提供給咱們的framework都是動態庫.

   3>.a和.framework的區別:

      * 通常來講共享庫文件都是使用的靜態庫。而靜態庫又分.a文件和.framework文件。

      * .framework其實是一種打包方式,它將頭文件,二進制文件和資源文件打包到一塊兒。

      *.a文件是一個純二進制文件,它必須配合頭文件使用。由於使用.a文件必定要同時導入頭文件,相比.framework更麻煩一點點,因此更推薦使用.framework。

   4>靜態庫文件的版本(4種)

       *  真機-Debug版本

      *  真機-Release版本

      *  模擬器-Debug版本

      *  模擬器-Release版本

     Debug(調試)版本:

        * 含完整的符號信息,以方便調試

        * 不會對代碼進行優化

     Release(發佈)版本:

        *  不會包含完整的符號信息

        *  執行代碼是進行過優化的

        *  大小會比Debug版本的略小

        * 在執行速度方面,Release版本會更快些(但不意味着會有顯著的提高)

    注意:因此咱們通常開發中都打包Release(發佈)版本,提供外界

   5>設備的CPU架構簡介

        *  模擬器:

            * 4s~5 : i386

            * 5s~6plus : x86_64

        *  真機:

            * 3gs~4s : armv7

            * 5~5c : armv7s (靜態庫只要支持了armv7,就能夠跑在armv7s的架構上)

            * 5s~6plus : arm64

二,製做靜態庫

  建立.a靜態庫

     第一步、新建工程。通常使用工程名就使用庫的名稱,好比我這裏用MethodLib來建立靜態庫,個人工程名就取名爲MethodLib,建立的.a靜態庫就是MethodLib.a。

                                                      

     第二步刪除自動生成的文件  替換成咱們須要的文件(也能夠不刪除,直接使用自動生成的文件)。

      第三步建立靜態文件

                                                                                                 

     第四步、暴露頭文件

          方式一:

          將頭文件添加到Copy Files中去:

              

                                                                  

             方式二:

                                                               

                                                 

     第五步、編譯靜態庫

           注意:須要修改Build Settings中的 Build Active Architecture Only以知足運行不一樣CPU環境的模擬器。將此設置爲NO。

                * 若是咱們選擇的是NO,那麼則會適配全部的機型,固然了編譯後的包的大小會有點大。

                   * 若是咱們選擇YES,那麼編譯的包只會適應當前機型以及版本低的機型,當咱們用高於這個手機型號的機型時可能不能用。

           

                                                   修改Build Settings(一).png

             在不一樣編譯環境下編譯會生成四種靜態庫,debug模擬器,debug真機,release模擬器,release真機,咱們須要將運行環境調至不一樣的狀態並生成如上四種形式的靜態庫。這裏只以一種狀況爲例:

     * 設置是Debug仍是release

        選擇Edit Scheme--> Buid Configuration設置爲release

                                                 設置是Debug仍是release(一).png

                                                 設置是Debug仍是release(二).png

      *  設置模擬器仍是真機

         就是設置模擬器仍是真機,由於以前咱們將只編譯當前環境設置爲NO,因此編譯出來的靜態庫會支持各類CPU環境。

                      

                                         設置模擬器仍是真機.png

 

      *   按住 command+b 編譯啊!(分別在模擬器和真機的環境下編譯才能生成所對應環境的靜態庫)

         你會發現你的靜態庫文件從紅色變成了黑色,這就是編譯完成了啊。能夠 show in finder 查看文件所在位置。

                                          show in finder.png

 

       

      * 能夠查看打包好的靜態庫

            

 

           你會看到以下四個目錄,這個就成功啦

 

     第六步、合併靜態庫(真機+模擬器)

            * 真機和模擬器的靜態庫,是不同的,不能同時適用在真機和模擬器上,但要知足這要求的話,要對編譯好的兩個靜態庫進行合併
               合併好壞:
                 好:開發過程當中既能夠在真機上調試,也能夠在模擬器上調試
                 壞:若是靜態庫太大,合併打包後,會很是大,所以不少第三方的靜態庫的.a是區分版本的
            * 合併產生新的靜態庫(終端操做)

               lipo -create 靜態文件1路徑 靜態文件2路徑 -output 輸出最終文件的目的路徑

              具體的步驟:

                 * 在終端輸入:lipo  -create 
                 * 將release-iphonesimulator下的.a拖進終端,輸入一個空格;
                 * 繼續將release-iphoneos 下.a 拖進終端,輸入空格;

                 * 繼續輸入:-output ,打個空格;
                 * 輸入合併後的.a所要放的文件路徑(假如放在桌面:個人桌面路徑爲:/Users/admin/Desktop/StaticLibaray.a (能夠本身定義.a文件的名字) ),回車,在相應的文件下便可生成一個.a,該.a便是合併後的.a

     第七步、使用靜態庫

            例如: 在你的要使用太靜態庫的項目中導入MethodLib.a文件和include文件夾中的相應的全部.h頭文件 便可使用

            

     注意點:

             * 記得把要暴漏的頭文件放到指定位置
             * 若是源文件中包含類別(category),則須要在使用的時候在Other linker Flags裏面添加-Objc的標誌,它的做用是把靜態庫中的全部和對象相關的文件都加載進來。                 不然連接器沒法把原有方法和類別整合起來。在64位系統中則須要使用-all_load來加載全部文件。

             * 文件大小.a文件的體積(通常狀況下)
                  * 真機用的.a > 模擬器用的.a
                  * 所合成.a == 真機用的.a + 模擬器用的.a

             * 關於靜態庫對CPU架構的支持,首先了解iOS設備CPU架構方面的知識,ARM是微處理器行業的一家知名企業,arm處理器以體積小和高性能的優點在嵌入式設備中廣                 泛使用,幾乎全部手機都是使用它的。

                  * 模擬器:iphone4s~5 : i386 iphone5s~6plus : x86_64
                  * 真機:iphone3gs~4s : armv7  iphone5~5c : armv7s (靜態庫只要支持了armv7,就能夠跑在armv7s的架構上) iphone5s~6plus : arm64,armv6, armv7, 

                             armv7s是ARM CPU的不一樣指令集,原則是向下兼容的。

                           例如iPhone4S CPU支持armv7, 但它同時兼容armv6,只是使用armv6指令可能沒法充分發揮它的特性。
             * 查看靜態庫.a對處理器架構的支持,先cd到.a文件的路徑下,命令行輸入:lipo -info xxxxx.a
 
             * 若是庫中還包含了一些資源文件(如圖片等),那麼資源文件也應該放在上面的文件夾中

  建立.framework靜態庫

 

     第一步、新建工程並選擇默認Target爲Cocoa Touch Framework, 如圖:

               

 

     第二步、給你的工程命名爲MJRefresh,生成的靜態庫將以標準的名稱格式出現.即MJRefresh.framework

               

     第三部、項目自動建立設置開放的頭文件和存放資源的Bundle文件,能夠看到一個紅色的MJRefresh.framework空的靜態庫

   

     第四步、刪除自動生成的MJRefresh.h文件

                          

     第五步、導入MJRefresh框架中的全部文件,應該暴露出來的.h文件默認都在Project下         

              

     第六步、.framework中有些類多是一些私有的輔助工具,不須要使用者看到,在這裏只須要把開放出去的類放到Public下, 如圖

                         

     第七步、而後選擇模擬器和Debug模式,編譯一下,Command + B,此時,雖然看到MJRefresh.framework仍爲紅色,其實已經生成能在模擬器上運行的.framework靜態庫,進入MJRefresh.framework目錄文件下,以及使用終端能夠看到生成的靜態庫。

選中靜態庫文件,獲取絕對路徑以下

 

在目錄下能夠看到生成的靜態庫

 

     第八步、再選擇真機,設置Release模式,編譯一下,Command + B,此時,雖然看到MJRefresh.framework變成黑色,生成能在真機上運行的靜態庫文件。

在目錄下以看到生成的靜態庫

     第九步、咱們隨意選擇一個靜態庫,點進去看這個庫文件中的具體內容,能夠看到一個MJRefresh可執行二進制的文件,資源MJRefresh.bundle,暴露出去的頭文件Headers等

     第十步、下面一步就是合併了,生成模擬器和真機環境下通用的二進制可執行文件MJRefresh,生成後看一下這個可執行文件使用的微處理器架構有哪些

                  

     第十一步、好了,合做完成,剩下的就是如何使用這個.framework靜態庫了。

      (1)咱們能夠隨意選擇一個生成的MJRefresh.framework,拷貝一下到桌面

     

       (2)而後再將合併後生成的可執二進制文件MJRefresh拷貝一下,粘貼到桌面上這個MJRefresh.framework文件中,替換裏面的MJRefresh,生成一個完成的靜態庫。

      (3)打開MJRefresh.framework/Modules/module.modulemap文件,能夠看到暴露的MJRefrsh.h文件被放在umbrella雨傘下保護起來了,因此咱們須要將其餘的全部暴露的.h文件放到MJRefresh.h文件中保護起來,否則會出現警告

     (4)咱們覺得此時大功告成,能夠測試代碼了,結果出現以下錯誤:

 

爲何會這樣的?由於咱們作的是靜態庫,在使用的時候須要額外加一個步驟,要把Framework同時添加到‘Embedded Binaries’中

 

此時再測試,發現沒問題了,大功告成,可喜可賀!

  製做靜態庫的注意點

  (1)注意
   不管是 .a 靜態庫仍是 .framework 靜態庫,最終須要的都是:二進制文件 + .h + 其它資源文件
  (2).a 和 .framework 的使用區別
  .a 自己是一個二進制文件,須要配上 .h 和 其它資源文件 才能使用
  .framework 自己已經包含了 .h 和 其它資源文件,能夠直接使用
  (3)圖片資源的處理
  若是靜態庫中用到了圖片資源,通常都放到一個bundle文件中,bundle名字通常跟 .a 或 .framework 名字一致
  bundle的建立:新建一個文件夾,修改擴展名爲 .bundle 便可,右擊bundle文件,顯示包內容,就能夠往bundle文件中放東西
  建議:本身製做的靜態庫中要用到的圖片資源,不建議直接以png的後綴名方式拖到項目中使用,而是推薦使用放到bundle文件中。這樣能夠避免靜態庫的圖片名和使用靜態庫的項目中存在的圖片產生衝突。
    * 新建一個文件夾,把須要打包的資源圖片放在裏面
  例如:
   
    * 修改擴展名爲 .bundle,敲回車,點擊添加。
  例如:
    
   (4)多文件處理
  若是靜態庫須要暴露出來的 .h 比較多,能夠考慮建立一個主頭文件(通常 主頭文件 和 靜態庫 同名)
  在主頭文件中包含全部其餘須要暴露出來的 .h 文件
  使用靜態庫時,只須要#import 主頭文件
  實際上蘋果官方就是這麼作的,例如:#import <UIKit/UIKit.h>
 (5).framework爲何既是靜態庫又是動態庫
  系統的 .framework 是動態庫
  咱們本身創建的 .framework 是靜態庫
 (6) 靜態庫中包含了Category(分類)
     若是靜態庫中包含了Category,有時候在使用靜態庫的工程中會報「方法找不到」的錯誤(unrecognized selector sent to instance)
     解決方案:在使用靜態庫的工程中配置Other Linker Flags爲-ObjC

相關文章
相關標籤/搜索