轉(zhuǎn)自https://blog.csdn.net/pangshishan1/article/details/72179898
引言
在開(kāi)發(fā)中.framework靜態(tài)庫(kù)還是比較常見(jiàn)的,比如:SDK,公司間的代碼合作等兴使。我們可以把一些不愿意讓別人見(jiàn)到的代碼系宜,用靜態(tài)庫(kù)的方式把它隱藏起來(lái),只留下.h文件顯示方法供編程人員使用鲫惶。而.a文件出了靜態(tài)庫(kù)本身外蜈首,還需要引入.h文件,而.framework就不需要如此欠母,由于.framework的方便性所以一般情況下我們見(jiàn)到的較多欢策。
什么是庫(kù)
庫(kù)從本質(zhì)上來(lái)說(shuō)是一種可執(zhí)行代碼的二進(jìn)制格式,可以被載入內(nèi)存中執(zhí)行赏淌。庫(kù)分靜態(tài)庫(kù)和動(dòng)態(tài)庫(kù)兩種踩寇。
iOS中的靜態(tài)庫(kù)有 .a 和 .framework兩種形式;動(dòng)態(tài)庫(kù)有.dylib 和 .framework 形式六水,后來(lái).dylib動(dòng)態(tài)庫(kù)又被蘋(píng)果替換成.tbd的形式俺孙。
靜態(tài)庫(kù)與動(dòng)態(tài)庫(kù)的區(qū)別
靜態(tài)庫(kù)和動(dòng)態(tài)庫(kù)是相對(duì)編譯期和運(yùn)行期的:靜態(tài)庫(kù)在程序編譯時(shí)會(huì)被鏈接到目標(biāo)代碼中辣卒,程序運(yùn)行時(shí)將不再需要改靜態(tài)庫(kù);而動(dòng)態(tài)庫(kù)在程序編譯時(shí)并不會(huì)被鏈接到目標(biāo)代碼中睛榄,只是在程序運(yùn)行時(shí)才被載入荣茫,因?yàn)樵诔绦蜻\(yùn)行期間還需要?jiǎng)討B(tài)庫(kù)的存在。
Bundle文件
Bundle文件可以用于存放資源文件场靴,可用于多人合作開(kāi)發(fā)啡莉,避免資源重名。里面可以存儲(chǔ)xib文旨剥、資源圖片等咧欣。Bundle文件是靜態(tài)的,不進(jìn)行編譯的轨帜。所以使用Bundle中的資源魄咕,就需要找到相應(yīng)的資源路徑。另外蚌父,我看別人博客上是說(shuō)哮兰,.a
文件中是無(wú)法用Bundle文件的,只能另存一個(gè)文件梢什;Framework靜態(tài)庫(kù)可以用Bundle文件奠蹬;我也沒(méi)試過(guò)朝聋,請(qǐng)?jiān)囘^(guò)的小伙伴留言告訴我嗡午,我就偷個(gè)懶,嘿嘿
總結(jié):同一個(gè)靜態(tài)庫(kù)在不同程序中使用時(shí)冀痕,每一個(gè)程序中都得導(dǎo)入一次荔睹,打包時(shí)也被打包進(jìn)去,形成一個(gè)程序言蛇。而動(dòng)態(tài)庫(kù)在不同程序中僻他,打包時(shí)并沒(méi)有被打包進(jìn)去腊尚,只在程序運(yùn)行使用時(shí)吨拗,才鏈接載入(如系統(tǒng)的框架如UIKit、Foundation等)婿斥,所以程序體積會(huì)小很多劝篷,但是蘋(píng)果不讓使用自己的動(dòng)態(tài)庫(kù),否則審核就無(wú)法通過(guò)民宿。
一娇妓、創(chuàng)建 .a 靜態(tài)庫(kù)
1. 新建工程。比如我們的工程名叫PSSTest活鹰,那么我們創(chuàng)建的.a靜態(tài)庫(kù)的名字最好就是前面加個(gè)lib哈恰,如libPSSTest.a只估。
-
新建工程 (選中xcode,按commond + shift + N)
圖 -
此時(shí)工程目錄是這個(gè)樣子着绷,.a文件還沒(méi)有被創(chuàng)建蛔钙,因此是紅色的
圖 你可以把圖中
libPSSTest.h
和.m
換成你自己要生成庫(kù)的文件(可以是多個(gè)),在這里我就不換了荠医,就用這兩個(gè)文件夸楣,我們?cè)?code>.h文件中添加一個(gè)方法+sayHello
,并在.m
中實(shí)現(xiàn)它
// 一定要記得在.h中聲明哦
+ (void)sayHello
{
NSLog(@".a靜態(tài)庫(kù):Hello, world!");
}
2. 添加Headers
-
按照下圖順序進(jìn)行操作
圖圖圖圖圖
這里需要注意的是暴露出來(lái)的頭文件中import的其他類也得添加到public中暴露出來(lái)子漩。
如果不想將import的類暴露出來(lái)豫喧,那么在頭文件中用@class 然后在對(duì)應(yīng)的.m文件中再import。
總之
1. 你再外面用到的類幢泼,一定要暴露出來(lái)紧显;
2. 你暴露出來(lái)的類,頭文件中導(dǎo)入的類也一定是暴露出來(lái)的
3. 如果提示導(dǎo)入頭文件報(bào)錯(cuò)缕棵,找不到文件孵班,找不到誰(shuí)暴露誰(shuí)就對(duì)了
3. 進(jìn)行打包前的一些配置
-
設(shè)置編譯模式,打開(kāi)xcode菜單Product -> Scheme -> Edit Scheme招驴,改成release模式篙程,如下圖
圖 -
編譯機(jī)器的選擇,如下圖别厘,一定要選擇NO虱饿。(如果選擇yes,生成部分機(jī)型触趴,選擇NO則適配所有機(jī)型氮发,想了解更多,請(qǐng)自行百度冗懦,總之爽冕,選NO就對(duì)了)
圖
4. 接下來(lái),我們進(jìn)行打包
操作簡(jiǎn)述:
1. 在真機(jī)情況下編譯 (Generic iOS Device)披蕉,并記錄下.a
文件的絕對(duì)路徑
2. 在模擬機(jī)情況下編譯(隨便吧颈畸,別賤嗖嗖的用iPhone4,雖然我也沒(méi)試過(guò)有沒(méi)有問(wèn)題吧没讲,有興趣可以試試[emj壞笑])眯娱,并記錄下.a
文件絕對(duì)路徑
3. 用命令行合并1、2部記錄的文件食零,到新的.a
文件困乒,名字最好取開(kāi)始我們?nèi)〉拿职桑钚校?code>lipo -create 文件1路徑 文件2路徑 -output 最終文件路徑
4. 把你要暴露的.h
文件和你已經(jīng)生成的.a
文件搞到一個(gè)文件夾里贰谣,這個(gè)文件夾就可以直接拖到工程里用啦
4.1 在真機(jī)情況下編譯 (Generic iOS Device)娜搂,并記錄下.a
文件的絕對(duì)路徑
4.2 在模擬機(jī)情況下編譯迁霎,并記錄下.a
文件絕對(duì)路徑,本操作和上步操作一模一樣百宇,只不過(guò)需要選擇一個(gè)模擬器考廉,隨便選吧,我是選的iPhone7P携御,不截圖了
4.3 使用命令行昌粤,合并剛剛記錄的兩個(gè)路徑,到另一個(gè)路徑啄刹,例如:
lipo -create
/Users/xxxxx/Library/Developer/Xcode/DerivedData/libPSSTest-bmfbhsxiqeajiigltpqjlxhhpjjh/Build/Products/Release-iphoneos/liblibPSSTest.a
空格/Users/shanhexia/Library/Developer/Xcode/DerivedData/libPSSTest-bmfbhsxiqeajiigltpqjlxhhpjjh/Build/Products/Release-iphonesimulator/liblibPSSTest.a
-output/Users/shanhexia/Desktop/libPSSTest.a
我是把合成之后的.a文件放到桌面上了
4.4 也是最后一步涮坐,把我們剛合成的.a
文件和想要暴露的.h
文件,弄到一個(gè)文件夾下
新建一個(gè)文件夾誓军,取名libPSSTest袱讹,把文件復(fù)制粘貼進(jìn)來(lái),如下圖
4.5 創(chuàng)建.a靜態(tài)庫(kù)就已經(jīng)創(chuàng)建完了昵时,我們來(lái)試試吧捷雕,導(dǎo)入剛剛4.4
創(chuàng)建的文件夾,導(dǎo)入頭文件壹甥,調(diào)用方法看看有沒(méi)有打印
4.6 補(bǔ)充:
- category是我們實(shí)際開(kāi)發(fā)項(xiàng)目中經(jīng)常用到的,把category打成靜態(tài)庫(kù)是沒(méi)有問(wèn)題的句柠,但是在用這個(gè)靜態(tài)庫(kù)的工程中浦译,調(diào)用category中的方法時(shí)會(huì)有找不到該方法的運(yùn)行時(shí)錯(cuò)誤(selector not recognized),解決辦法是:在使用靜態(tài)庫(kù)的工程中配置other linker flags的值為-ObjC俄占。
- 如果一個(gè)靜態(tài)庫(kù)很復(fù)雜管怠,需要暴露的.h比較多的話淆衷,就可以在靜態(tài)庫(kù)的內(nèi)部創(chuàng)建一個(gè).h文件(一般這個(gè).h文件的名字和靜態(tài)庫(kù)的名字相同)缸榄,然后把所有需要暴露出來(lái)的.h文件都集中放在這個(gè).h文件中,而那些原本需要暴露的.h都不需要再暴露了祝拯,只需要把.h暴露出來(lái)就可以了甚带。
二、創(chuàng)建.Framework靜態(tài)庫(kù)
1. 新建工程佳头。比如我們的工程名叫PSSFramework
-
新建工程 (選中xcode鹰贵,按commond + shift + N)
圖 -
添加文件到工程,并且在
PSSFramework.h
文件中導(dǎo)入接口文件
圖片.png 在PSSObject中添加
+sayHello
方法康嘉,并在.m
中實(shí)現(xiàn)
// 一定要在`.h`中暴露方法哦
+ (void)sayHello
{
NSLog(@".framework: Hello, world!");
}
2. 添加Headers
- 這一步和創(chuàng)建
.a
的時(shí)候一模一樣碉输,請(qǐng)往上翻。不過(guò)跟.a
不同的是亭珍,貌似它里面本來(lái)就有Headers了敷钾,但是只給你暴露了一個(gè).h
文件枝哄,需要多暴露的話再自己拖吧
3. 打包前的一些配置
-
設(shè)置編譯模式,打開(kāi)xcode菜單Product -> Scheme -> Edit Scheme阻荒,改成release模式挠锥,如下圖(這一步和生成
.a
一樣,我就借用圖了)
圖 -
編譯機(jī)器的選擇侨赡,如下圖蓖租,一定要選擇NO。(這一步和生成
.a
一樣羊壹,我就借用圖了)
圖 修改生成的Mach-O格式(很重要)
4. 打包Framework (合并模擬器版framework和真機(jī)版framework)
-
分別在真機(jī)(Generic iOS Device)和模擬器編譯蓖宦,這次不用記錄路徑,一會(huì)我會(huì)標(biāo)出合并哪兩個(gè)文件
注意: 合并的命令同上面相似油猫,不同之處是:framework靜態(tài)庫(kù)合并的不是framework,而是framework下的一個(gè)二進(jìn)制文件球昨,即下圖中我標(biāo)出來(lái)的文件。
lipo -create 第一個(gè)framework下二進(jìn)制文件的絕對(duì)路徑 第二個(gè)framework下二進(jìn)制文件的絕對(duì)路徑 -output 最終的二進(jìn)制文件路徑眨攘。
圖片.png圖片.png -
接下來(lái)我們進(jìn)行合并主慰,我們把新合并的二進(jìn)制文件放到
Release-iphoneos
和Release-iphonesimulator
同一個(gè)文件夾下命令行如下
lipo -create/Users/xxxxx/Library/Developer/Xcode/DerivedData/PSSFramework-ehyytcfdvluxetbnmqcfzosxrbtu/Build/Products/Release-iphoneos/PSSFramework.framework/PSSFramework``/Users/shanhexia/Library/Developer/Xcode/DerivedData/PSSFramework-ehyytcfdvluxetbnmqcfzosxrbtu/Build/Products/Release-iphonesimulator/PSSFramework.framework/PSSFramework
-output/Users/shanhexia/Library/Developer/Xcode/DerivedData/PSSFramework-ehyytcfdvluxetbnmqcfzosxrbtu/Build/Products/PSSFramework
- 圖片.png
-
通過(guò)上一步,我們已經(jīng)把我們要的Framework搞到桌面上了鲫售,接下來(lái)我們就試試能不能用吧共螺。將Framework拖進(jìn)工程,導(dǎo)入框架情竹,調(diào)用方法藐不,看看有沒(méi)有打印
我試了,確實(shí)是能用秦效,不截圖了
三雏蛮、Bundle文件的使用
1. 創(chuàng)建Bundle
桌面上創(chuàng)建一個(gè)文件夾,把文件夾的后綴改為. bundle這時(shí)他就變成一個(gè)bundle文件了阱州,這時(shí)我們右鍵顯示包內(nèi)容就可以把對(duì)應(yīng)的圖片資源等放進(jìn)文件中挑秉,然后把他丟進(jìn)工程中就可以使用了。
2. 使用方法 (親測(cè)可用)
結(jié)束語(yǔ)
實(shí)際上苔货,在項(xiàng)目中犀概,我們用別人的Framework
或.a
比較多一些,開(kāi)發(fā)自己的項(xiàng)目的時(shí)候夜惭,我倒是沒(méi)怎么用到過(guò)姻灶,但是公司如果希望一部分代碼需要保密,是可以用這種方式的诈茧〔恚或者你開(kāi)發(fā)了一個(gè)功能,不想開(kāi)源,也可以這樣搞曾沈。