庫是共享程序代碼的方式。ios
庫從本質上來講是一種可執行代碼的二進制格式,能夠被載入內存中執行。庫分靜態庫和動態庫兩種。
iOS中的靜態庫有 .a 和 .framework兩種形式;動態庫有.dylib 和 .framework 形式,後來.dylib動態庫又被蘋果替換成.tbd的形式。xcode
靜態庫: 連接時完整地拷貝至可執行文件中,被屢次使用就有多份冗餘拷貝。架構
動態庫: 連接時不復制,程序運行時由系統動態加載到內存,供程序調用,系統只加載一次,多個程序共用,節省內存。[ios暫時只容許使用系統動態庫];框架
靜態庫和動態庫是相對編譯期和運行期的:靜態庫在程序編譯時會被連接到目標代碼中,程序運行時將再也不須要改靜態庫;而動態庫在程序編譯時並不會被連接到目標代碼中,只是在程序運行時才被載入,由於在程序運行期間還須要動態庫的存在。
總結:同一個靜態庫在不一樣程序中使用時,每個程序中都得導入一次,打包時也被打包進去,造成一個程序。而動態庫在不一樣程序中,打包時並無被打包進去,只在程序運行使用時,才連接載入(如系統的框架如UIKit、Foundation等),因此程序體積會小不少,可是蘋果不讓使用本身的動態庫,不然審覈就沒法經過。iphone
.a和.framework模塊化
.dylib和.frameworkui
系統的.framework是動態庫,咱們本身創建的.framework是靜態庫。spa
.a是一個純二進制文件,.framework中除了有二進制文件以外還有資源文件。debug
.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暴露出來就能夠了。
第一步,新建工程。通常使用工程名就使用庫的名稱,好比我這裏用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)
二. 架構的分類
一、模擬器架構: 2種
i386 : 32位架構 4S ~ 5
x86_64 : 64位架構 5S ~ 如今的機型
二、真機架構: 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. 靜態庫打包時, 並不會打包資源文件 --> 須要手動拖出去
第一步、新建工程。通常使用工程名就使用庫的名稱
第二步、導入須要打包的資源文件,同時把資源文件須要外界訪問的.h文件導入到系統推薦的.h中
第三步、真機,模擬器編譯一下。可能會須要輸入AppleID 。導出的文件沒有包含.h
第四步、導出.h
第五步、能夠查看一下 沒合併模擬器架構以前包含幾個同.a(可跳過此步)(真機包含兩個,模擬器包含一個)
第六步、合成架構【同.a五六步詳細看上邊】
第七步,合併架構【真機和模擬器】【注意 合併以後的動態/靜態庫要與原來的名稱一致。否則用的時候編譯報錯】
第八步、動態庫變靜態庫【默認是動態】好處是未來使用時不須要設置添加動態庫(也就是下邊的方法)
最後步、
Framework製做後, 默認是動態庫. 使用時, 須要設置一下: Tarteg --> General --> Embedded Binaries --> 須要添加對應的動態庫 【注意 要是製做的時候更改成靜態庫的話,就不用執行此方法】
謝謝。