一、前言
前段時(shí)間看的一本書上說:“隔著一段距離看械哟,很多有趣的知識(shí)看起來都很唬人疏之。”比如說這篇我要總結(jié)的“靜態(tài)庫知識(shí)”暇咆,在我初出茅廬的時(shí)候著實(shí)覺得那些后綴名為“.frameworke”锋爪、“.a”、“.dylib”的文件很神秘爸业,很高冷其骄。那時(shí)我雖然知道只要導(dǎo)入一個(gè)庫就能引用庫里面很多封裝好的東西,但對(duì)這個(gè)“庫”究竟是什么“鬼”扯旷,一直都是云里霧里拯爽。好了廢話不多說,看下去就知道它是個(gè)什么“鬼”钧忽。
二 毯炮、一些概念的補(bǔ)充
1逼肯、 什么是庫?
所謂庫就是程序代碼的集合否副,是共享程序代碼的一種方式汉矿。
2、 庫的分類
根據(jù)程序代碼的開源情況备禀,庫可以分為兩類
- 開源庫
源代碼是公開的洲拇,你可以看到具體實(shí)現(xiàn)。比如GitHub上比較出名的第三方框架AFNetworking曲尸、SDWebImage赋续。 - 閉源庫
不公開源代碼,只公開調(diào)用的接口另患,看不到具體的實(shí)現(xiàn)纽乱,是一個(gè)編譯后的二進(jìn)制文件。這種常見于一些公司的SDK包昆箕,比如高德地圖SDK鸦列、環(huán)信即時(shí)通訊SDK等等。而閉源庫又分為兩類:靜態(tài)庫和動(dòng)態(tài)庫鹏倘。本篇重點(diǎn)要講的便是其中的靜態(tài)庫薯嗤。
3、靜態(tài)庫和動(dòng)態(tài)庫的存在形式和使用區(qū)別
存在形式:
- 靜態(tài)庫
以".a"或者“.framework”為文件后綴名 - 動(dòng)態(tài)庫
以".dylib"或者“.framework”為文件后綴名
使用區(qū)別:
- 靜態(tài)庫鏈接時(shí)會(huì)被完整的復(fù)制到可執(zhí)行文件中纤泵,被多次使用就有多份拷貝骆姐。
- 動(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)存带射。
4、iOS 設(shè)備的CPU架構(gòu)
模擬器:
4s-5: i386
5s-7 Plus: x86_64真機(jī)(iOS設(shè)備):
armv6: iPhone循狰、iPhone 2庸诱、iPhone 3G、iPod Touch(第一代)晤揣、iPod Touch(第二代)
armv7: iPhone 3Gs、iPhone 4朱灿、iPhone 4s昧识、iPad、iPad 2
armv7s: iPhone 5盗扒、iPhone 5c (靜態(tài)庫只要支持了armv7,就可以在armv7s的架構(gòu)上運(yùn)行)
arm64: iPhone 5s跪楞、iPhone 6缀去、iPhone 6 Plus、iPhone 6s甸祭、iPhone 6s Plus缕碎、iPad Air、iPad Air2池户、iPad mini2咏雌、iPad mini3
注:真機(jī)iPhone7、iPhone7 Plus A10處理器到底是什么架構(gòu)暫時(shí)不得而知校焦,沒查到相關(guān)資料碴萧,貌似還沒公布倦零,但是模擬器是x86_64。
三、打包靜態(tài)庫
因?yàn)殪o態(tài)庫存在兩種形式几莽,我們先看.a靜態(tài)庫的打包
- .a文件靜態(tài)庫打包
1、打開Xcode創(chuàng)建一個(gè)新的工程漫萄,這里以Xcode8為例舌厨,選擇工程如下:
2、創(chuàng)建工程完畢后井氢,再創(chuàng)建一個(gè)工具類StaticLibTool弦追,添加一個(gè)方法用于測(cè)試
StaticLibTool.m文件實(shí)現(xiàn)如下
3毙沾、運(yùn)行工程進(jìn)行打包
運(yùn)行完畢后骗卜,我們會(huì)看到工程中Products文件夾下的libStaticLib.a文件由紅色變成了黑色。右鍵show in finder可以在其目錄下找到它左胞。這就是我們打包好的.a靜態(tài)文件了寇仓。
但是這樣就完了嗎?當(dāng)然沒有烤宙,我們知道靜態(tài)庫存在的最大意義是隱藏代碼的具體實(shí)現(xiàn)遍烦,但是這也隱藏的太徹底了,總要公開些接口或者頭文件供人調(diào)用吧躺枕。
4服猪、公開接口頭文件
targets->Build Phases->Copy Files->"+"你需要公開的頭文件
這里我們把新建的測(cè)試類StaticLibTool.h公開
公開頭文件后,我們?cè)侔瓷鲜?拐云、2罢猪、3流程重新運(yùn)行打包,我們會(huì)得到一個(gè)頭文件和一個(gè).a靜態(tài)庫(如下圖)叉瘩,而這正是我們所需要的膳帕。
5、新建一個(gè)可運(yùn)行的工程薇缅,把這兩個(gè)打包好的文件拖入項(xiàng)目測(cè)試
選擇Iphone7模擬器運(yùn)行危彩,程序正常運(yùn)行攒磨,點(diǎn)擊模擬器屏幕,打印日志如下:
我們可以看到輸出沒有問題汤徽,打包.a靜態(tài)庫大功告成娩缰。
但是,別高興的太早谒府。當(dāng)我把模擬器切換成Iphone5運(yùn)行時(shí)拼坎,編譯直接不通過,報(bào)錯(cuò)如下:
上圖“Undefined symbols for architecture i386”是什么意思呢狱掂?意思是我們的libStaticLib.a靜態(tài)庫不支持i386架構(gòu)演痒。那i386又是什么鬼?不清楚的可以拉上去看“iOS 設(shè)備的CPU架構(gòu)”趋惨,這里就不多做解釋了鸟顺。
iPhone 5模擬器正好是i386架構(gòu),而我們打包的靜態(tài)庫不支持器虾。但是iPhone 7模擬器運(yùn)行卻沒有問題讯嫂,這說明我們打包的靜態(tài)庫正好支持iPhone 7模擬器 的cpu架構(gòu) x86_64。如何查看靜態(tài)庫所支持的架構(gòu)兆沙,請(qǐng)看下一步欧芽。
6、終端查看靜態(tài)庫所支持的架構(gòu)
終端->cd進(jìn)入庫文件路徑->lipo -info 庫名
上圖可以看到葛圃,我們的靜態(tài)庫僅支持x86_64架構(gòu)千扔,也就是說此靜態(tài)庫只可運(yùn)行在iphone5s-iphone7plus之間的模擬器設(shè)備。所以剛才我們運(yùn)行iphone5模擬器時(shí)库正,編譯會(huì)報(bào)錯(cuò)曲楚。
到這里就可以進(jìn)一步解釋下,打包靜態(tài)庫時(shí)褥符,你用什么模擬器運(yùn)行龙誊,打包出來的靜態(tài)庫就支持什么模擬器的架構(gòu),而剛才我打包時(shí)是用iPhone7運(yùn)行喷楣,所以僅支持架構(gòu)x86_64趟大。那么這就太麻煩了,可以打包一個(gè)靜態(tài)庫支持多種架構(gòu)的模擬器嗎铣焊?答案是肯定的逊朽,請(qǐng)看下一步。
7曲伊、設(shè)置適配所有模擬器架構(gòu)
project -> buildSeting -> Build Active Architecture Only 設(shè)為NO
設(shè)置完成后惋耙,我們重新運(yùn)行打包靜態(tài)庫文件(這時(shí)你可隨便選一個(gè)模擬器),按照上述第6步終端查看其支持的架構(gòu),我們可以看到終端輸出的結(jié)果是同時(shí)支持 i386和x86_64绽榛,這也就意味著同時(shí)支持所有模擬器。
到這里打包.a靜態(tài)庫已經(jīng)告一段落婿屹,但是按上述流程打包的只能在模擬器上跑灭美,真機(jī)是不能運(yùn)行的,因?yàn)閕os真機(jī)設(shè)備跟模擬器的架構(gòu)又不一樣(怎么不一樣自己拉上去看)昂利,所以還沒完(我也不想啊 )届腐,請(qǐng)看下一步
8、打包支持真機(jī)架構(gòu)的靜態(tài)庫
所有流程都跟上面的一樣蜂奸,只是我們運(yùn)行打包時(shí)要選擇真機(jī)運(yùn)行犁苏,如下圖你可以選擇自己插上去的真機(jī),也可以選擇Generic ios Devices扩所。當(dāng)然不要忘記了設(shè)置支持所有真機(jī)機(jī)型架構(gòu): Build Active Architecture Only 設(shè)為NO围详。
我們可以看下打包出來的終端查看結(jié)果如下:
上圖可以看到同時(shí)支持armv7和arm64,也就是支持所有ios設(shè)備祖屏。好了到此打包.a靜態(tài)庫算是告一段落助赞。
- .frameworke文件靜態(tài)庫打包
1、依然Xcode創(chuàng)建一個(gè)新的工程FrameworkeLib袁勺,選擇工程如下:
創(chuàng)建完成后我們可以看到雹食,工程本身自帶一個(gè)FrameworkeLib.h文件,這是類似一個(gè)主頭文件一樣的東西
2期丰、創(chuàng)建需要測(cè)試的類群叶,為了方便我把上述打包.a的測(cè)試類StaticLibTool直接拖來使用。
3钝荡、設(shè)置支持所有模擬器架構(gòu)或真機(jī)架構(gòu)(和打包.a第7步驟一樣)
4街立、公開頭文件
target-Build Phases - Headers -把需要公開的頭文件從project拖入Public
5、設(shè)置打包的是靜態(tài)庫化撕。因?yàn)閯?dòng)態(tài)庫也可以是以framework形式存在几晤,所以需要設(shè)置,否則默認(rèn)打出來的是動(dòng)態(tài)庫
target->BuildSetting ->搜索關(guān)鍵字mach->Mach-o Type 設(shè)為Static Library(這個(gè)默認(rèn)選項(xiàng)是動(dòng)態(tài)的)
6植阴、選中真機(jī)或模擬器運(yùn)行設(shè)備打包(與打包.a一樣)蟹瘾,完成后Products文件夾下的FrameworkeLib.framework文件由紅色變成了黑色,右鍵show in finder 顯示如下:
FrameworkeLib.framework拖入項(xiàng)目便可直接使用掠手,這里就不再進(jìn)行測(cè)試了憾朴。此外還要補(bǔ)充的一點(diǎn)是,打包靜態(tài)庫的時(shí)候還需注意打包的是測(cè)試版(Debug)還是發(fā)布版(Release)喷鸽,這個(gè)根據(jù)你自己的需求決定众雷,而如何進(jìn)行設(shè)置請(qǐng)下一步驟。
7、設(shè)置打包靜態(tài)庫的測(cè)試版和發(fā)布版(.a和.frameworke)
product -> scheme -> Edit scheme -> Run->選擇Debug或Release
三 砾省、END