前言
如果你想將你開(kāi)發(fā)的控件與別人分享焕襟,一種方法是直接提供源代碼文件掸驱。然而肛搬,這種方法并不是很優(yōu)雅。它會(huì)暴露所有的實(shí)現(xiàn)細(xì)節(jié)毕贼,而這些實(shí)現(xiàn)你可能并不想開(kāi)源出來(lái)滚婉。此外,開(kāi)發(fā)者也可能并不想看到你的所有代碼帅刀,因?yàn)樗麄兛赡軆H僅希望將你的這份漂亮代碼的一部分植入自己的應(yīng)用中让腹。
另一種方法是將你的代碼編譯成靜態(tài)庫(kù)(library),讓其他開(kāi)發(fā)者添加到自己的項(xiàng)目中扣溺。然而骇窍,這需要你一并公布所有的公開(kāi)的頭文件,實(shí)在是非常不方便锥余。
你需要一種簡(jiǎn)單的方法來(lái)編譯你的代碼腹纳,這種方法應(yīng)該使得你的代碼易分享,并且在多個(gè)工程中易復(fù)用驱犹。你需要的是一種方法來(lái)打包你的靜態(tài)庫(kù)嘲恍,將所有的頭文件放到一個(gè)單元中,這樣你就可以立刻將其加入到你的項(xiàng)目中并使用雄驹。
OS X完美地支持這一點(diǎn)佃牛,因?yàn)閄code就提供了一個(gè)項(xiàng)目模板,包含著默認(rèn)構(gòu)建目標(biāo)(target)和可以容納類(lèi)似于圖片医舆、聲音俘侠、字體等資源的文件象缀。你可以為iOS創(chuàng)建Framework,不過(guò)這是一個(gè)比較復(fù)雜的手工活爷速,如果你跟著教程走央星,你將學(xué)到怎么樣跨過(guò)路障,順利地完成Framework的創(chuàng)建惫东。
.a和.framework的異同
可以參考這篇文章.a和.framework的區(qū)別莉给。
一、什么是庫(kù)廉沮?
庫(kù)是共享程序代碼的方式禁谦,一般分為靜態(tài)庫(kù)和動(dòng)態(tài)庫(kù)。
二废封、靜態(tài)庫(kù)與動(dòng)態(tài)庫(kù)的區(qū)別州泊?
靜態(tài)庫(kù):鏈接時(shí)完整地拷貝至可執(zhí)行文件中,被多次使用就有多份冗余拷貝漂洋。
動(dòng)態(tài)庫(kù):鏈接時(shí)不復(fù)制遥皂,程序運(yùn)行時(shí)由系統(tǒng)動(dòng)態(tài)加載到內(nèi)存,供程序調(diào)用刽漂,系統(tǒng)只加載一次演训,多個(gè)程序共用,節(jié)省內(nèi)存贝咙。
三样悟、iOS里靜態(tài)庫(kù)形式?
.a和.framework
四庭猩、iOS里動(dòng)態(tài)庫(kù)形式窟她?
.dylib和.framework
五、framework為什么既是靜態(tài)庫(kù)又是動(dòng)態(tài)庫(kù)蔼水?
系統(tǒng)的.framework是動(dòng)態(tài)庫(kù)震糖,我們自己建立的.framework是靜態(tài)庫(kù)。
六趴腋、a與.framework有什么區(qū)別吊说?
.a是一個(gè)純二進(jìn)制文件,.framework中除了有二進(jìn)制文件之外還有資源文件优炬。
.a文件不能直接使用颁井,至少要有.h文件配合,.framework文件可以直接使用蠢护。
.a + .h + sourceFile = .framework雅宾。
建議用.framework.
七、為什么要使用靜態(tài)庫(kù)糊余?
方便共享代碼秀又,便于合理使用单寂。
實(shí)現(xiàn)iOS程序的模塊化贬芥⊥抡蓿可以把固定的業(yè)務(wù)模塊化成靜態(tài)庫(kù)。
和別人分享你的代碼庫(kù)蘸劈,但不想讓別人看到你代碼的實(shí)現(xiàn)昏苏。
開(kāi)發(fā)第三方sdk的需要。
八威沫、制作靜態(tài)庫(kù)時(shí)的幾點(diǎn)注意:
1 注意理解:無(wú)論是.a靜態(tài)庫(kù)還.framework靜態(tài)庫(kù)贤惯,我們需要的都是二進(jìn)制文件+.h+其它資源文件的形式,不同的是棒掠,.a本身就是二進(jìn)制文件孵构,需要我們自己配上.h和其它文件才能使用,而.framework本身已經(jīng)包含了.h和其它文件烟很,可以直接使用颈墅。
2 圖片資源的處理:兩種靜態(tài)庫(kù),一般都是把圖片文件單獨(dú)的放在一個(gè).bundle文件中雾袱,一般.bundle的名字和.a或.framework的名字相同恤筛。.bundle文件很好弄,新建一個(gè)文件夾芹橡,把它改名為.bundle就可以了毒坛,右鍵,顯示包內(nèi)容可以向其中添加圖片資源林说。
3 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。
4 如果一個(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)就可以了。
可以看出.a的封裝和.framework的封裝差不多垢乙,也有模擬器和真機(jī)合并的過(guò)程锨咙,通過(guò)上邊的圖片我們可以看出.a 和.framework的區(qū)別,就是.a+.h+soureFile=.framework追逮±业叮可以看出我們直接封裝.framework其實(shí)是最好的粹舵。那么我們就來(lái)看看framework怎么封裝的。
另外關(guān)于.a的封裝大家可以參考iOS如何生成.a文件骂倘。
目標(biāo)
本文將基于Xcode10創(chuàng)建一個(gè)簡(jiǎn)單的工程來(lái)教大家如何制作一個(gè)自己的framework眼滤,目的就是簡(jiǎn)單易學(xué)的制作framework。這種方法可以使得你的代碼易分享历涝,在多個(gè)工程中復(fù)用诅需,并且可以隱藏實(shí)現(xiàn)細(xì)節(jié),控制公開(kāi)的頭文件荧库。
創(chuàng)建完了FrameWork堰塌,我們看看這個(gè)FrameWork的結(jié)構(gòu):
我在里面簡(jiǎn)單的添加了Dog這個(gè)類(lèi),看看在這個(gè)類(lèi)里我寫(xiě)了什么內(nèi)容分衫。
#import "Dog.h"
@implementation Dog
- (void)say{
NSLog(@"I'm a dog.");
}
@end
接下來(lái)對(duì)我們的這個(gè).framework靜態(tài)庫(kù)進(jìn)行一些簡(jiǎn)單的設(shè)置场刑,如下圖所示:
1、首先是Dead Code Stripping設(shè)置為NO蚪战,網(wǎng)上對(duì)此項(xiàng)的解釋如下牵现,大致意思是如果開(kāi)啟此項(xiàng)就會(huì)對(duì)代碼中的”dead”、”unreachable”的代碼過(guò)濾屎勘,不過(guò)這個(gè)開(kāi)關(guān)是否關(guān)閉施籍,似乎沒(méi)有多大影響,不過(guò)為了完整還原framework中的代碼概漱,將此項(xiàng)關(guān)閉也未曾不可丑慎。
2、然后將Link With Standard Libraries關(guān)閉瓤摧,我想可能是為了避免重復(fù)鏈接
3竿裂、最后將Mach-O Type設(shè)為Static Library,framework可以是動(dòng)態(tài)庫(kù)也可以是靜態(tài)庫(kù)照弥,對(duì)于系統(tǒng)的framework是動(dòng)態(tài)庫(kù)腻异,而用戶(hù)制作的framework只能是靜態(tài)庫(kù)。
接下里就是設(shè)置我們有那些頭文件是需要公開(kāi)的这揣,如下圖設(shè)置:
還要記得把要公開(kāi)的類(lèi)添加到我們的FrameWorkTest.h中悔常,比如下面是我們例子中的截圖:
最后要做的就是打包制作我們這個(gè)FrameWork了:
command+B 按照我們下圖的選擇,打包出這個(gè)FrameWork:
這個(gè)時(shí)候你就會(huì)看到FrameWork項(xiàng)目里的Products文件多了我們的.framework文件给赞。你Show in Finder一下就會(huì)看到下面這樣的兩個(gè)文件夾了机打,一個(gè)就是真機(jī)一個(gè)就是模擬機(jī)的:
接下來(lái)就是生成我們.framework文件的最后一步了:利用終端把模擬機(jī)和真機(jī)的文件我們合并成一份:
把上圖中我們標(biāo)注的FrameWorkTest文件進(jìn)行下面的操作:
在終端中輸入命令:lipo -create 模擬機(jī)和真機(jī)的FrameWorkTest文件路徑(直接拉到終端就會(huì)顯示)-output 真機(jī)的FrameWorkTest文件路徑
具體的例子我們看下面我們終端中的信息:
最后將輸出路徑生成FrameworkTest文件拷貝替換掉真機(jī)模式下FrameworkTest.framework中的FrameworkTest文件就可以了。
這下我們就可以使用了
現(xiàn)在把我們.framework拷貝到我們的測(cè)試項(xiàng)目中片迅。
運(yùn)行一下残邀,大功告成。
最后需要注意的是
1、在制作framework或者lib的時(shí)候芥挣,如果使用了category驱闷,則使用改Framework的程序運(yùn)行category方法時(shí)會(huì)crash,此時(shí)需要在該工程中 other linker flags添加參數(shù) -ObjC
2空免、帶有圖片資源的需要把圖片打包成Bundle文件空另,和framework一起拷貝到相應(yīng)的項(xiàng)目中。
3鼓蜒、公開(kāi)的類(lèi)中如果引用的private的類(lèi)痹换,打包以后對(duì)外會(huì)報(bào)錯(cuò)征字,找不到那個(gè)private的類(lèi)都弹,需要把那個(gè)private的.h放到公開(kāi)文件中
4、namespace 沖突匙姜。靜態(tài)庫(kù)用了某第三方庫(kù)畅厢,項(xiàng)目也用了同樣的第三方庫(kù),在編譯的時(shí)候就會(huì)有 duplicate symbol 錯(cuò)誤氮昧,因?yàn)橛袃煞萃瑯拥牡谌綆?kù)框杜。解決辦法就是把用到的第三方庫(kù)加上自定義前綴,包括類(lèi)名袖肥、delegate 協(xié)議咪辱、常量名,尤其需要注意 Category 的方法名要修改椎组。
參考文檔:
1油狂、iOS 封裝.framework 以及使用
2、iOS封裝功能生成 .framework