寫(xiě)在前面
過(guò)程有點(diǎn)長(zhǎng)痒筒,但是比較細(xì)節(jié)宰闰,看官各取所需茬贵。
創(chuàng)建靜態(tài)庫(kù)工程
可以先了解iOS庫(kù) .a與.framework區(qū)別,靜態(tài)庫(kù)可以分為.a和.framework類(lèi)型的的文件移袍。Xcode創(chuàng)建的靜態(tài)庫(kù)工程解藻,默認(rèn)編譯后獲得的靜態(tài)庫(kù)文件是.a類(lèi)型的。
Xcode(9.1)創(chuàng)建分為動(dòng)態(tài)庫(kù)工程和靜態(tài)庫(kù)工程:
而我們又需要.framework類(lèi)型的(而對(duì)bundle類(lèi)型的TARGETS進(jìn)行一些設(shè)置葡盗,即可得到一個(gè)輸出framework文件的工程)具體操作如下:
1)選擇上圖的靜態(tài)庫(kù)螟左,創(chuàng)建一個(gè)靜態(tài)庫(kù)工程:
2)因?yàn)榫幾g生成.a文件,所以刪除默認(rèn)的TRAGETS觅够,后面重新添加一個(gè)bundle類(lèi)型的即可胶背。
3)有些教程說(shuō),在Product->Scheme->Manage Schemes中喘先,需要?jiǎng)h除關(guān)聯(lián)的build項(xiàng)(其實(shí)只要新建的TARGETS的名稱(chēng)相同钳吟,是不用刪除的,只要新建了窘拯,就會(huì)重新關(guān)聯(lián)上):
4)刪除工程文件:
5)這個(gè)時(shí)候可以新建一個(gè)bundle類(lèi)型的TARGETS了(注意此處是bundle是屬于macOS類(lèi)型的红且,后續(xù)需要一些設(shè)置):
上面說(shuō)到,新建的時(shí)候使用與工程同名的來(lái)創(chuàng)建新的TARGETS涤姊,即可不用刪除默認(rèn)的build關(guān)聯(lián)項(xiàng):
6)創(chuàng)建完畢暇番,可以看出,bundle在默認(rèn)情況下思喊,是適用于Mac OS的:
因此需要我們對(duì)這個(gè)bundle類(lèi)型的TARGETS做一些設(shè)置:
創(chuàng)建bundle類(lèi)型TARGETS的一些設(shè)置:
參考:ios 制作自已的framework
1)
Base SDK:Lstest iOS(iOS XX.XX)
2)指令集設(shè)置
Architectures:Standard architectures - $(ARCHS_STANDARD)默認(rèn)之外壁酬,添加一個(gè):armv7s
Valid Architectures: armv7 armv7s arm64
具體原因點(diǎn)這里
3)Dead Code Stripping用于刪除對(duì)象文件中不需要加載的符號(hào),減小二進(jìn)制文件大泻蘅巍(此處為何關(guān)閉舆乔,我也不知道原因,哪位大神知道的告知一聲)
Dead Code Stripping:NO
4)關(guān)聯(lián)標(biāo)準(zhǔn)庫(kù)(此處關(guān)閉庄呈,我也不知道原因蜕煌,哪位大神知道的告知一聲)
Link with Standard Libraries:NO
5)庫(kù)類(lèi)型
可參考:淺談 SDK 開(kāi)發(fā)(一)五種 Mach-O 類(lèi)型的凜冬之戰(zhàn)
Mac-O Type:Relocatable Object File
6)
在 Packaging 中,將 “Wrapper Extention” 改為“framework”
7)
info文件將 “Bundle OS Type Code” 改為 “FMWK”(Framework 的意思)
8)設(shè)置SDK支持的最低系統(tǒng)
Build Settings -> Deployment -> iOS Deployment Target 修改具體參數(shù)
也可在 General -> Deployment Info -> Deployment Target 處設(shè)置诬留,兩處設(shè)置等效
至此斜纪,相關(guān)設(shè)置完成,即可選擇相應(yīng)環(huán)境文兑,Cmd+B 進(jìn)行編譯盒刚,以獲得framework
打開(kāi)StaticLibObject.framework所在的文件夾,發(fā)現(xiàn)這個(gè):
編譯后的framework包绿贞,是真機(jī)環(huán)境和模擬器分開(kāi)的因块,其實(shí)是因?yàn)槎咚С值闹噶罴煌唧w得看你的Architectures設(shè)置籍铁,必要的時(shí)候涡上,可以使用lipo命令來(lái)合并兩個(gè)文件成一個(gè)文件趾断,使其即支持真機(jī),又支持模擬器吩愧。
我們查看芋酌,或者合并的文件就是這里面的文件:
查看真機(jī)的(請(qǐng)看我上面的關(guān)于Architectures的設(shè)置):
$ lipo -info WxxStaticLibFramework
Architectures in the fat file: WxxStaticLibFramework are: armv7 armv7s arm64
查看模擬器的:
$ lipo -info WxxStaticLibFramework
Non-fat file: WxxStaticLibFramework is architecture: x86_64
修改下模擬器的文件名,將其扔進(jìn)真機(jī)的文件夾雁佳,執(zhí)行合并命令
注意咯:最好合并輸出的文件與原來(lái)的保持名字一致脐帝,替換掉原來(lái)的文件即可。否則framework中會(huì)找不到這個(gè)文件L侨ā6赂埂!(修改了名字還能關(guān)聯(lián)的星澳,有好的辦法請(qǐng)告訴我)
lipo -create 模擬器庫(kù) 真機(jī)庫(kù) -output 最終庫(kù)
$ lipo -create StaticLibObject StaticLibObjectSimulator -output StaticLibLastFramework
查看最終合并的所支持的指令集:
lipo -info StaticLibLastFramework
查詢(xún)結(jié)果:
Architectures in the fat file: StaticLibLastFramework are: x86_64 armv7 armv7s arm64
StaticLibLastFramework已經(jīng)可以同時(shí)用于真機(jī)和模擬器了疚顷!可是這種方式有點(diǎn)麻煩,每次重新編譯募判,都需要重新合并文件荡含,據(jù)說(shuō)還可以用腳本的方式來(lái)合并咒唆,待我研究后再補(bǔ)充届垫,這里先占個(gè)坑。
framework的使用
framework的使用全释,無(wú)非就是對(duì)外暴露.h文件装处,.h文件中有寫(xiě)好的被人使用的方法。這里拋磚引玉浸船。下面具體說(shuō)明:
1)新建對(duì)外文件妄迁,并提供方法 +(void)staticLibSDKTest;
內(nèi)部方法實(shí)現(xiàn):
+(void)staticLibSDKTest{
NSLog(@"static lib sdk test method");
}
2)暴露頭文件
Build Phases -> + ->New Header Phase
注意:添加完默認(rèn)是歸類(lèi)到Project中,將需要暴露的.h文件李命,手動(dòng)拖進(jìn)Public中即可登淘。
重新編譯,即可發(fā)現(xiàn)封字,頭文件已經(jīng)對(duì)外暴露了:
3)創(chuàng)建一個(gè)普通工程StaticLibObjectDemo
來(lái)測(cè)試剛剛創(chuàng)建的framework黔州,跑這個(gè)工程的時(shí)候,注意真機(jī)和模擬器的區(qū)別阔籽!framework的指令集和工程的運(yùn)行環(huán)境要對(duì)上流妻!當(dāng)然,合并執(zhí)行真機(jī)和執(zhí)行文件的另當(dāng)別論了笆制。
引入framework的操作這里無(wú)需贅敘了:
4)在使用的地方 #import
#import <StaticLibObject/StaticLibSDK.h>
5)調(diào)用StaticLibSDK.h中的方法
[StaticLibSDK staticLibSDKTest];
很開(kāi)心的快捷鍵Cmd+R绅这,發(fā)現(xiàn)報(bào)錯(cuò)了:
具體錯(cuò)誤:framework not found StaticLibObject
果然,原先的文件被我刪除了在辆,留下的可執(zhí)行文件是支持模擬器和真機(jī)的通用文件StaticLibLastFramework
证薇,連文件名都不一樣的度苔,難怪找不到:
上圖中的同級(jí)中有個(gè)info.plist文件,本來(lái)以為改動(dòng)里面的Executable file的名字浑度,就可以了林螃,沒(méi)想到還是不行!
(無(wú)奈俺泣,重新合并疗认,合并后的文件與原來(lái)的同名稱(chēng)):
各自環(huán)境編譯完成,修改各自的執(zhí)行文件的名字為:真機(jī)的StaticLibObjec1
和模擬器的StaticLibObject2
伏钠,執(zhí)行合并生成StaticLibObject
:
$ lipo -create StaticLibObjec1 StaticLibObject2 -output StaticLibObject
然后把StaticLibObject
文件丟回去.framework文件夾横漏。
再次編譯,即可成功輸出:
StaticLibObjectDemo[1980:867317] static lib sdk test method
至此熟掂,整個(gè)創(chuàng)建和使用bundle類(lèi)型創(chuàng)建的framework全部完成缎浇。
制作靜態(tài)庫(kù)的注意事項(xiàng)
從這里搬過(guò)來(lái)的
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)就可以了。