Xcode7 中建立靜態庫:.a 和 .framework html
1、簡單介紹架構
1.什麼是庫?框架
庫是程序代碼的集合,是共享程序代碼的一種方式iphone
2.庫的分類工具
根據源代碼的公開狀況,庫能夠分爲2種類型性能
(1)開源庫測試
公開源代碼,能看到具體實現ui
好比SDWebImage、AFNetworkingspa
(2)閉源庫命令行
不公開源代碼,是通過編譯後的二進制文件,看不到具體實現
主要分爲:靜態庫、動態庫
2、靜態庫和動態庫
1.靜態庫和動態庫的存在形式
靜態庫:.a 和 .framework
動態庫:.dylib 和 .framework
2.靜態庫和動態庫在使用上的區別
靜態庫:連接時,靜態庫會被完整地複製到可執行文件中,被屢次使用就有多份冗餘拷貝(圖1所示)
動態庫:連接時不復制,程序運行時由系統動態加載到內存,供程序調用,系統只加載一次,多個程序共用,節省內存(圖2所示)
3、靜態庫簡介:
一、靜態庫分爲:
真機—Debug(調試)版本、
真機—Release(發佈)版本、
模擬器—Debug版本、
模擬器—Release版本;
開發中通常都打包Release(發佈)版本,將真機和模擬器版本合併,提供外界。
二、使用場景:在項目開發的過程當中,例如兩個公司之間業務交流,不可能把源代碼都發送給另外一個公司,這時候將私密內容打包成靜態庫,別人只能調用接口,而不能知道其中實現的細節。
4、用Xcode7建立.a靜態庫
.a文件版本(以製做SDWebImage靜態庫爲例)
一、新建項目,點擊iOS—Framework&—Cocoa Touch Static Library。
給你的工程命名爲SDWebImageStaticLib
二、系統自動生成以工程名命名的.h和.m文件,可自定義的在目錄下添加或刪除文件,注意目錄下Products文件夾有一個.a文件爲紅色,說明文件並不存在,須要接下來的處理就是將是本身寫的庫文件中全部的.m文件都放入.a文件中私有隱藏起來。
這裏咱們將系統生成的.h和.m文件刪除。
3.選中TARGETS下的庫文件名,建立對外暴露的頭文件
建立完以後
4.將SDWebImage下的全部文件導入到SDWebImageStaticLib下
注意:第三步驟和第四步驟是能夠調換的,只不過調換後須要手動的將須要暴露的頭文件添加進去,因此不調換能夠幫助咱們完成。
此時默認的狀況下,暴露的頭文件都在Project下,應該移動到Public下
以前:
移動後:
五、而後點擊左上角,選擇Edit Scheme,Build Configuration下選擇Release,先注意檢查下面Release是否爲NO:Yes表示只編譯選中模擬器設備對應的架構,No則爲編譯全部模擬器設備支持的cup架構(Debug版本同理),選擇NO,而後分別在模擬器和真機下Command+B編譯一下,會看到Products文件夾下的.a文件變爲黑色,這個.a文件就是咱們想要獲得的靜態庫,這裏會出現一個問題你先編譯的模擬器會發現.a依然是紅色,你須要模擬器和真機都編譯後.a纔會變成黑色,這應該是Xcode自己的問題。
<1>
<2>
<3>
這3步設置完後,選擇真機模式編譯一下,Command + B,此時看到.a靜態庫文件變成了黑色。
而後將上面的第<3>步改成Debug,再選擇模擬器編譯一下,Command + B,就建立了模擬器環境下的.a文件,截圖以下同樣。
能夠在終端看到,真機Release發佈模式和模擬器Debug測試模式的.a文件都存在
文件爲:
六、合併真機和模擬器.a文件,在終端輸入如下命令行:lipo -create 模擬器.a文件的路徑 真機.a文件的路徑 -output 合併後的保存路徑(最終會獲得一個合併後的libSDWebImageStaticLib.a文件,再將暴露出來的.h頭文件一塊兒複製出來。
七、使用:只需將libSDWebImageStaticLib.a和暴露出來的.h頭文件導入工程目錄下就可供外界使用,這樣就很好的保護了本身的實現源代碼,不被他人篡改和偷竊。
8.這裏再補充一下:
<1>.文件大小.a文件的體積(通常狀況下)
真機用的.a > 模擬器用的.a
所合成.a == 真機用的.a + 模擬器用的.a
<2>.
注:關於靜態庫對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
<3>.
若是庫中還包含了一些資源文件(如圖片等),那麼資源文件也應該放在上面的文件夾中。
5、用Xcode7建立.framework靜態庫,以MJRefresh爲例
1.新建工程並選擇默認Target爲Cocoa Touch Framework, 如圖:
2.給你的工程命名爲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,生成後看一下這個可執行文件使用的微處理器架構有哪些:
11.好了,合併替換完成,剩下的就是如何使用這個最終的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’中
此時再測試,發現沒問題了,大功告成,可喜可賀!
6、製做靜態庫的注意點
(1)注意:
不管是 .a 靜態庫仍是 .framework 靜態庫,最終須要的都是:二進制文件 + .h + 其它資源文件
(2).a 和 .framework 的使用區別
.a 自己是一個二進制文件,須要配上 .h 和 其它資源文件 才能使用
.framework 自己已經包含了 .h 和 其它資源文件,能夠直接使用
(3)圖片資源的處理
若是靜態庫中用到了圖片資源,通常都放到一個bundle文件中,bundle名字通常跟 .a 或 .framework 名字一致
bundle的建立:新建一個文件夾,修改擴展名爲 .bundle 便可,右擊bundle文件,顯示包內容,就能夠往bundle文件中放東西
建議:本身製做的靜態庫中要用到的圖片資源,不建議直接以png的後綴名方式拖到項目中使用,而是推薦使用放到bundle文件中。這樣能夠避免靜態庫的圖片名和使用靜態庫的項目中存在的圖片產生衝突。
1)新建一個文件夾,把須要打包的資源圖片放在裏面
例如:
2)修改擴展名爲 .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