【轉】iOS靜態庫 【.a 和framework】【超詳細】


原文網址:https://my.oschina.net/kaqijiang/blog/649632

一、什么是庫?

庫是共享程序代碼的方式。

庫從本質上來說是一種可執行代碼的二進制格式,可以被載入內存中執行。庫分靜態庫和動態庫兩種。
iOS中的靜態庫有 .a 和 .framework兩種形式;動態庫有.dylib 和 .framework 形式,后來.dylib動態庫又被蘋果替換成.tbd的形式。

二、靜態庫與動態庫的區別?

靜態庫: 鏈接時完整地拷貝至可執行文件中,被多次使用就有多份冗余拷貝。

動態庫: 鏈接時不復制,程序運行時由系統動態加載到內存,供程序調用,系統只加載一次,多個程序共用,節省內存。[ios暫時只允許使用系統動態庫];

靜態庫和動態庫是相對編譯期和運行期的:靜態庫在程序編譯時會被鏈接到目標代碼中,程序運行時將不再需要改靜態庫;而動態庫在程序編譯時並不會被鏈接到目標代碼中,只是在程序運行時才被載入,因為在程序運行期間還需要動態庫的存在。
總結:同一個靜態庫在不同程序中使用時,每一個程序中都得導入一次,打包時也被打包進去,形成一個程序。而動態庫在不同程序中,打包時並沒有被打包進去,只在程序運行使用時,才鏈接載入(如系統的框架如UIKit、Foundation等),所以程序體積會小很多,但是蘋果不讓使用自己的動態庫,否則審核就無法通過。

三、iOS里靜態庫形式?

.a和.framework

四、iOS里動態庫形式?

.dylib和.framework

五、framework為什么既是靜態庫又是動態庫?

系統的.framework是動態庫,我們自己建立的.framework是靜態庫。

六、a與.framework有什么區別?

.a是一個純二進制文件,.framework中除了有二進制文件之外還有資源文件。

.a文件不能直接使用,至少要有.h文件配合,.framework文件可以直接使用。

.a + .h + sourceFile = .framework。

建議用.framework.

七、為什么要使用靜態庫?

方便共享代碼,便於合理使用。

實現iOS程序的模塊化。可以把固定的業務模塊化成靜態庫。

和別人分享你的代碼庫,但不想讓別人看到你代碼的實現。

開發第三方sdk的需要。

八、制作靜態庫時的幾點注意:

1注意理解:無論是.a靜態庫還.framework靜態庫,我們需要的都是二進制文件+.h+其它資源文件的形式,不同的是,.a本身就是二進制文件,需要我們自己配上.h和其它文件才能使用,而.framework本身已經包含了.h和其它文件,可以直接使用。

2圖片資源的處理:兩種靜態庫,一般都是把圖片文件單獨的放在一個.bundle文件中,一般.bundle的名字和.a或.framework的名字相同。.bundle文件很好弄,新建一個文件夾,把它改名為.bundle就可以了,右鍵,顯示包內容可以向其中添加圖片資源。

3category是我們實際開發項目中經常用到的,把category打成靜態庫是沒有問題的,但是在用這個靜態庫的工程中,調用category中的方法時會有找不到該方法的運行時錯誤(selector not recognized),解決辦法是:在使用靜態庫的工程中配置other linker flags的值為-ObjC。

4如果一個靜態庫很復雜,需要暴露的.h比較多的話,就可以在靜態庫的內部創建一個.h文件(一般這個.h文件的名字和靜態庫的名字相同),然后把所有需要暴露出來的.h文件都集中放在這個.h文件中,而那些原本需要暴露的.h都不需要再暴露了,只需要把.h暴露出來就可以了。

九、創建.a靜態庫

第一步,新建工程。一般使用工程名就使用庫的名稱,比如我這里用LIB來創建靜態庫,我的工程名就取名為LIB,創建的.a靜態庫就是LIB.a。

第二步,刪除.m文件,保留.h文件, 一般靜態庫都有一個總的.h文件,方便外部導入頭文件。然后導入需要打包的源文件。

第三步,先用真機,編譯一次,再用模擬器編譯一次。就可以生成.a文件(必須先用真機要不然,不能生成)。

第四步,Xcode生成的.a文件默認沒有導出.h文件。需要自己添加。

第五步,導出Products靜態庫的配置(其實不用設置此步驟,如果真機編譯的話,生成導出的時候系統默認會變成Releasse[但是模擬器不會(如果不改這里 得需要把Debug設置為NO)])

 

注意:如果第五步中,不將Build Configuration改為Release,則打包出來的靜態庫會存於【Debug-iphoneos】和【Debug-iphonesimulator】兩個文件夾下。
我們一般都使用Release模式,因為程序最終發布之后是Release版的,所以靜態庫也是在Release模式下使用。

第六步,合成模擬器的架構【默認:模擬器編譯只會生成對應的1種架構,真機編譯會合成兩種架構】

如果第六步這里,設置為YES,那么編譯出來的.a靜態庫就只包含當前設備的架構。


舉個例子:如果我們選擇iPhone 5模擬器【Command+B】編譯,則編譯出來的.a靜態庫只能用iPhone4s~5模擬器跑程序, 用iPhone5s~6plus,則會報找不到x86_64的libFMDB庫。

 

設置為 NO 之后,【Command+B】不管選擇哪個【模擬器】,則都會把【386   : 32位架構   4S ~ 5】【x86_64 : 64位架構   5S ~ 現在的機型】的架構都打包合並。

 

【注】【真機】不設置 [Build Active Architecture Only] 也默認會自動合並的armv7 和amr64架構 。但是 armv7s架構被蘋果放棄了,真機要想合並armv7s的話需要進行如下操作再編譯。(其實沒必要設置這個)

第七步,合並架構【真機和模擬器】

真機和模擬器合並: lipo -create 靜態庫1.a(路徑) 靜態庫2.a(路徑) -output 新靜態庫.a  

第八步,資源包的問題

 1. 靜態庫的資源, 都應該放到后綴為.bundle的文件夾中 --> 避免文件與本地文件重名被覆蓋, 導致加載資源文件出錯【注:要加載bundel路徑】

 2. 靜態庫打包時, 並不會打包資源文件 --> 需要手動拖出去

 

 一. 經典報錯:

 找不到符號在XX架構上

 Undefined symbols for architecture x86_64(armv7/armv7s/amr64/i386)

 

 二. 架構的分類

 1、模擬器架構: 2種

        i386   : 32位架構  4S ~ 5

        x86_64 : 64位架構   5S ~ 現在的機型

 

 2、真機架構: 3種

        armv7 : 32位架構    3GS ~ 4S

        armv7s: 特殊的架構   5 ~ 5C   (此架構有問題, 有的程序變得更快, 有的程序變得更慢)

        amr64 : 64位架構    5S ~ 現在的機型

 

 64位/32位: 內存尋址不同

 

 三. 如何查看靜態庫架構

 找到Products文件夾, 如果.a文件是黑色, 右鍵打開 到 Products文件夾

終端中 lipo -info

 

 

 Generic iOS Device編譯出來的OS可用, 有2種架構:armv7/ arm64 (不包含armv7s: 特殊的架構)

 iPhone6S模擬器編譯出來的: x86_64

 iPhone4S模擬器編譯出來的: i386

 (不設置Build Active Architecture Only的情況下真機編譯2種架構, 模擬器編譯:對應的1種架構)

 

 四. 合成架構

 一般來說, 只需要前兩步即可

 1. 模擬器架構的合成: Target --> Build Settings --> Build Active Architecture Only(是否只編譯當前架構) --> Debug 改為NO(改為NO, 模擬器就可以直接合成2種架構)

 2. 真機和模擬器合並: lipo -create 靜態庫1.a 靜態庫2.a -output 新靜態庫.a 

 3.* armv7s這個架構, 在2014年10月份的xcode版本更新中, 取消了默認導出此架構. 可以不用支持此架構. 

    如果要支持, 需要手動添加3個架構.

 

五. Debug和Release版本

 一般來說, 我們應該發布的是release版本.

 debug:調試版本, 系統本身也會有一些調試代碼. 此版本體積會稍大, 運行會稍慢

 release: 發布版本, 系統會去除調試代碼, 體積變小, 運行速度變快. 對用戶來說沒有明顯的感覺

 

 六. 到底要不要合成多個架構

 真機和模擬器合成的好處: 調試會非常方便, 缺點是體積會變大(一種架構就占用一部分體積).

 真機和模擬器不合成的好處:體積小,  缺點是調試稍顯麻煩.

 

 七. 資源包的問題

 1. 靜態庫的資源, 都應該放到后綴為.bundle的文件夾中 --> 避免文件重名被覆蓋, 導致加載資源文件出錯

 2. 靜態庫打包時, 並不會打包資源文件 --> 需要手動拖出去

 

十、創建framework靜態庫

 

第一步、新建工程。一般使用工程名就使用庫的名稱

第二步、導入需要打包的資源文件,同時把資源文件需要外界訪問的.h文件導入到系統推薦的.h中

第三步、真機,模擬器編譯一下。可能會需要輸入AppleID 。導出的文件沒有包含.h

第四步、導出.h

第五步、可以查看一下 沒合並模擬器架構之前包含幾個同.a(可跳過此步)(真機包含兩個,模擬器包含一個)

第六步、合成架構【同.a五六步詳細看上邊】

第七步,合並架構【真機和模擬器】【注意 合並之后的動態/靜態庫要與原來的名稱一致。不然用的時候編譯報錯】

 

第八步、動態庫變靜態庫【默認是動態】好處是將來使用時不需要設置添加動態庫(也就是下邊的方法)

最后步、

Framework制作后, 默認是動態庫. 使用時, 需要設置一下: Tarteg --> General --> Embedded Binaries --> 需要添加對應的動態庫 【注意 要是制作的時候更改為靜態庫的話,就不用執行此方法】

 

 

謝謝。

 

補充:開發的app使用framework,archive后提示“Undefined symbols for architecture armv7”,需要在Build Settings -> Build Active Architecture only設置為Yes

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM