引言
在開發(fā)中.framework靜態(tài)庫還是比較常見的,比如:SDK,公司間的代碼合作等懊蒸。我們可以把一些不愿意讓別人見到的代碼荣倾,用靜態(tài)庫的方式把它隱藏起來,只留下.h文件顯示方法供編程人員使用骑丸。而.a文件出了靜態(tài)庫本身外逃呼,還需要引入.h文件,而.framework就不需要如此者娱,由于.framework的方便性所以一般情況下我們見到的較多抡笼。
什么是庫
庫從本質(zhì)上來說是一種可執(zhí)行代碼的二進制格式,可以被載入內(nèi)存中執(zhí)行黄鳍。庫分靜態(tài)庫和動態(tài)庫兩種推姻。
iOS中的靜態(tài)庫有 .a 和 .framework兩種形式;動態(tài)庫有.dylib 和 .framework 形式框沟,后來.dylib動態(tài)庫又被蘋果替換成.tbd的形式藏古。
靜態(tài)庫與動態(tài)庫的區(qū)別
靜態(tài)庫和動態(tài)庫是相對編譯期和運行期的:靜態(tài)庫在程序編譯時會被鏈接到目標(biāo)代碼中增炭,程序運行時將不再需要改靜態(tài)庫;而動態(tài)庫在程序編譯時并不會被鏈接到目標(biāo)代碼中拧晕,只是在程序運行時才被載入隙姿,因為在程序運行期間還需要動態(tài)庫的存在。
Bundle文件
Bundle文件可以用于存放資源文件厂捞,可用于多人合作開發(fā)输玷,避免資源重名。里面可以存儲xib文靡馁、資源圖片等欲鹏。Bundle文件是靜態(tài)的,不進行編譯的臭墨。所以使用Bundle中的資源赔嚎,就需要找到相應(yīng)的資源路徑。另外胧弛,我看別人博客上是說尤误,.a
文件中是無法用Bundle文件的,只能另存一個文件结缚;Framework靜態(tài)庫可以用Bundle文件袄膏;我也沒試過,請試過的小伙伴留言告訴我掺冠,我就偷個懶,嘿嘿
總結(jié):同一個靜態(tài)庫在不同程序中使用時码党,每一個程序中都得導(dǎo)入一次德崭,打包時也被打包進去,形成一個程序揖盘。而動態(tài)庫在不同程序中眉厨,打包時并沒有被打包進去,只在程序運行使用時兽狭,才鏈接載入(如系統(tǒng)的框架如UIKit憾股、Foundation等),所以程序體積會小很多箕慧,但是蘋果不讓使用自己的動態(tài)庫服球,否則審核就無法通過。
一颠焦、創(chuàng)建 .a 靜態(tài)庫
1. 新建工程斩熊。比如我們的工程名叫PSSTest,那么我們創(chuàng)建的.a靜態(tài)庫的名字最好就是前面加個lib伐庭,如libPSSTest.a粉渠。
-
新建工程 (選中xcode分冈,按commond + shift + N)
-
此時工程目錄是這個樣子,.a文件還沒有被創(chuàng)建霸株,因此是紅色的
你可以把圖中
libPSSTest.h
和.m
換成你自己要生成庫的文件(可以是多個)雕沉,在這里我就不換了,就用這兩個文件去件,我們在.h
文件中添加一個方法+sayHello
坡椒,并在.m
中實現(xiàn)它
// 一定要記得在.h中聲明哦
+ (void)sayHello
{
NSLog(@".a靜態(tài)庫:Hello, world!");
}
2. 添加Headers
-
按照下圖順序進行操作
這里需要注意的是暴露出來的頭文件中import的其他類也得添加到public中暴露出來。
如果不想將import的類暴露出來箫攀,那么在頭文件中用@class 然后在對應(yīng)的.m文件中再import肠牲。
總之
- 你再外面用到的類,一定要暴露出來靴跛;
- 你暴露出來的類缀雳,頭文件中導(dǎo)入的類也一定是暴露出來的
- 如果提示導(dǎo)入頭文件報錯,找不到文件梢睛,找不到誰暴露誰就對了
3. 進行打包前的一些配置
-
設(shè)置編譯模式肥印,打開xcode菜單Product -> Scheme -> Edit Scheme,改成release模式绝葡,如下圖
-
編譯機器的選擇深碱,如下圖,一定要選擇NO藏畅。(如果選擇yes敷硅,生成部分機型,選擇NO則適配所有機型愉阎,想了解更多绞蹦,請自行百度,總之榜旦,選NO就對了)
4. 接下來幽七,我們進行打包
操作簡述:
- 在真機情況下編譯 (Generic iOS Device),并記錄下
.a
文件的絕對路徑- 在模擬機情況下編譯(隨便吧溅呢,別賤嗖嗖的用iPhone4澡屡,雖然我也沒試過有沒有問題吧,有興趣可以試試[emj壞笑])咐旧,并記錄下
.a
文件絕對路徑- 用命令行合并1驶鹉、2部記錄的文件,到新的
.a
文件铣墨,名字最好取開始我們?nèi)〉拿职闪豪鳎钚校?code>lipo -create 文件1路徑 文件2路徑 -output 最終文件路徑- 把你要暴露的
.h
文件和你已經(jīng)生成的.a
文件搞到一個文件夾里,這個文件夾就可以直接拖到工程里用啦
4.1 在真機情況下編譯 (Generic iOS Device),并記錄下.a
文件的絕對路徑
4.2 在模擬機情況下編譯词顾,并記錄下.a
文件絕對路徑八秃,本操作和上步操作一模一樣,只不過需要選擇一個模擬器肉盹,隨便選吧昔驱,我是選的iPhone7P,不截圖了
4.3 使用命令行上忍,合并剛剛記錄的兩個路徑骤肛,到另一個路徑,例如:
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
文件腋颠,弄到一個文件夾下
新建一個文件夾,取名libPSSTest吓笙,把文件復(fù)制粘貼進來淑玫,如下圖
4.5 創(chuàng)建.a靜態(tài)庫就已經(jīng)創(chuàng)建完了,我們來試試吧面睛,導(dǎo)入剛剛4.4
創(chuàng)建的文件夾絮蒿,導(dǎo)入頭文件,調(diào)用方法看看有沒有打印
4.6 補充:
- category是我們實際開發(fā)項目中經(jīng)常用到的土涝,把category打成靜態(tài)庫是沒有問題的,但是在用這個靜態(tài)庫的工程中幌墓,調(diào)用category中的方法時會有找不到該方法的運行時錯誤(selector not recognized)但壮,解決辦法是:在使用靜態(tài)庫的工程中配置other linker flags的值為-ObjC。
- 如果一個靜態(tài)庫很復(fù)雜常侣,需要暴露的.h比較多的話蜡饵,就可以在靜態(tài)庫的內(nèi)部創(chuàng)建一個.h文件(一般這個.h文件的名字和靜態(tài)庫的名字相同),然后把所有需要暴露出來的.h文件都集中放在這個.h文件中袭祟,而那些原本需要暴露的.h都不需要再暴露了,只需要把.h暴露出來就可以了捞附。
二巾乳、創(chuàng)建.Framework靜態(tài)庫
1. 新建工程。比如我們的工程名叫PSSFramework
-
新建工程 (選中xcode鸟召,按commond + shift + N)
-
添加文件到工程胆绊,并且在
PSSFramework.h
文件中導(dǎo)入接口文件
在PSSObject中添加
+sayHello
方法,并在.m
中實現(xiàn)
// 一定要在`.h`中暴露方法哦
+ (void)sayHello
{
NSLog(@".framework: Hello, world!");
}
2. 添加Headers
- 這一步和創(chuàng)建
.a
的時候一模一樣欧募,請往上翻压状。不過跟.a
不同的是,貌似它里面本來就有Headers了,但是只給你暴露了一個.h
文件种冬,需要多暴露的話再自己拖吧
3. 打包前的一些配置
-
設(shè)置編譯模式镣丑,打開xcode菜單Product -> Scheme -> Edit Scheme,改成release模式娱两,如下圖(這一步和生成
.a
一樣莺匠,我就借用圖了)
-
編譯機器的選擇,如下圖十兢,一定要選擇NO趣竣。(這一步和生成
.a
一樣,我就借用圖了)
修改生成的Mach-O格式(很重要)
4. 打包Framework (合并模擬器版framework和真機版framework)
-
分別在真機(Generic iOS Device)和模擬器編譯旱物,這次不用記錄路徑遥缕,一會我會標(biāo)出合并哪兩個文件
注意: 合并的命令同上面相似,不同之處是:framework靜態(tài)庫合并的不是framework,而是framework下的一個二進制文件宵呛,即下圖中我標(biāo)出來的文件单匣。
lipo -create 第一個framework下二進制文件的絕對路徑 第二個framework下二進制文件的絕對路徑 -output 最終的二進制文件路徑。
接下來我們進行合并烤蜕,我們把新合并的二進制文件放到
Release-iphoneos
和Release-iphonesimulator
同一個文件夾下
命令行如下
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
通過上一步封孙,我們已經(jīng)把我們要的Framework搞到桌面上了,接下來我們就試試能不能用吧讽营。將Framework拖進工程虎忌,導(dǎo)入框架,調(diào)用方法橱鹏,看看有沒有打印
我試了膜蠢,確實是能用,不截圖了
三莉兰、Bundle文件的使用
1. 創(chuàng)建Bundle
桌面上創(chuàng)建一個文件夾挑围,把文件夾的后綴改為. bundle這時他就變成一個bundle文件了,這時我們右鍵顯示包內(nèi)容就可以把對應(yīng)的圖片資源等放進文件中糖荒,然后把他丟進工程中就可以使用了杉辙。
2. 使用方法 (親測可用)
結(jié)束語
實際上,在項目中捶朵,我們用別人的Framework
或.a
比較多一些蜘矢,開發(fā)自己的項目的時候,我倒是沒怎么用到過综看,但是公司如果希望一部分代碼需要保密品腹,是可以用這種方式的『毂或者你開發(fā)了一個功能舞吭,不想開源,也可以這樣搞(雖然應(yīng)該可以反編譯,反正我不會)羡鸥,但是我不推薦蔑穴;畢竟大家把自己的代碼開源可以互相促進彼此的成長嘛,嘿嘿_
如果覺得寫得還行兄春,點個Star唄
同時也歡迎評論中指出本文存在的bug澎剥,或者疑問,互相促進赶舆!
作者郵箱:pangshishan@aliyun.com
github地址:https://github.com/Pangshishan
qq/微信: 704158807