iOS動態(tài)庫和靜態(tài)庫知識專題導(dǎo)航
3.復(fù)雜.a靜態(tài)庫的生成和使用(包含Bundle文件和Category分類文件)
4.framework動態(tài)庫和靜態(tài)庫的生成和使用
(一)iOS中的庫簡介
? ? 最近項目中用到庫,在庫的生成和使用中遇到一些問題,于是各種百度和google,發(fā)現(xiàn)有關(guān)庫的博客和文章都很多,但是都比較零散和瑣碎,我總結(jié)了一下,希望能夠給和我有一樣困擾的iOS開發(fā)者們一些幫助吧!總結(jié)不到位的地方請大家多多指正!
? ? iOS中的所謂的庫,就是一些封裝好的代碼的集合,可以用來共享程序代碼的一種方式。在iOS中庫,其實就是一些三方框架,并且這些庫一般都是靜態(tài)的(動態(tài)庫審核是必掛的,你懂的-_-),所以這片文章是以靜態(tài)庫為例的。
(二)iOS中庫的分類
1.根據(jù)程序代碼庫的開源情況,庫可以分為兩類:開源庫和閉源庫兩類
????開源庫:開源庫的所有代碼都是公開的,可見的;你可以看到.h文件里的接口,也可以看到.m文件里的具體實現(xiàn)。在GitHub上有很多這樣第三方框架,比如AFNetworking、SDWebImage、MJRefresh等
????閉源庫:源代碼是封閉的,不可見的;只公開調(diào)用.h文件中的調(diào)用接口,看不到.m文件中接口的具體實現(xiàn),是一個編譯后的二進制文件。這種情況在企業(yè)開發(fā)中比較常見,一般在企業(yè)開發(fā)中為避免一些核心技術(shù)的或者常用框架泄漏,出于安全性和穩(wěn)定性的考慮,不想被外界知道,會把核心代碼打包成靜態(tài)庫,只暴露.h 文件給程序員使用。比如百度地圖SDK、高德地圖SDK、環(huán)信即時通訊SDK、友盟分享SDK等等。
2.根據(jù)程序代碼庫在app存在的形式,庫可以分為兩類:動態(tài)庫和靜態(tài)庫兩類
? ? 靜態(tài)庫:在app開發(fā)中,以".a"或者“.framework”為文件后綴名為靜態(tài)庫。一般app集成的都為靜態(tài)庫,集成動態(tài)庫,蘋果審核通不過。
? ? 動態(tài)庫:在app開發(fā)中,以".tdb"(Xcode7以前為".dylib")或者“.framework”為文件后綴名。WWDC2014上發(fā)布的Xcode6 beta時,蘋果在iOS上開放了動態(tài)庫,比如我們經(jīng)常用到的系統(tǒng)庫Foundation.framework/UIKit.framework/AppKit.framework等,都是動態(tài)庫。但殘忍的是,蘋果上并不允許我們使用自己創(chuàng)建的動態(tài)庫。不過由于framework是一種優(yōu)秀的資源打包方式,擁有無窮智慧的程序員們便想出了以framework的形式打包靜態(tài)庫的招數(shù),因此我們平時看到的第三方發(fā)布的framework無一例外都是靜態(tài)庫,集成自定義動態(tài)庫是上不了AppStore的。
3.動態(tài)庫和靜態(tài)庫使用中的不同
? ? 同一手機系統(tǒng)下,多個程序使用同一個靜態(tài)庫時,每個程序和靜態(tài)庫鏈接時會被完整的復(fù)制到可執(zhí)行文件中,被多次使用就有多份拷貝。
? ??同一手機系統(tǒng)下,多個程序使用同一個動態(tài)庫時,每個程序和動態(tài)庫鏈接時不會復(fù)制,某個程序運行時由系統(tǒng)動態(tài)加載到內(nèi)存,供程序調(diào)用。而且系統(tǒng)只加載一次,多個程序共用庫中的代碼,節(jié)省內(nèi)存。
4.根據(jù)開發(fā)環(huán)境的不同可以分為四種文件版本
?? 靜態(tài)庫文件根據(jù)調(diào)試和發(fā)布分為四個版本:真機-Debug版本、真機-Release版本、模擬器-Debug版本、模擬器-Release版本。
????Debug版本和Release版本的區(qū)別:Debug版本含完整的符號信息,以方便調(diào)試,但是不會對代碼進行優(yōu)化;Release版本執(zhí)行代碼是進行過優(yōu)化,大小會比Debug版本的略小,執(zhí)行速度比Debug版本快(但不意味著會有顯著的提升),但是不會包含完整的符號信息;我們一般開發(fā)中都打包Release(發(fā)布)版本,提供外界使用。
(三)iOS中設(shè)備的分類
1.模擬器:
????4s-5: i386?針對intel通用微處理器32位處理器
????5s-8 Plus: x86_64?是針對x86架構(gòu)的64位處理器
2.真機:
????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)上運行)
????arm64: iPhone 5s、iPhone 6、iPhone 6 Plus、iPhone 6s、iPhone 6s Plus、iPhone 7、iPhone 7 Plus、iPhone 7s、iPhone 7s Plus、iPhone SE、iPhone 8、iPhone 8 Plus、iPhone X、iPad Air、iPad Air2、iPad mini2、iPad mini3、iPad Pro
(四)庫文件中可以包含的文件內(nèi)容
? ?1. 靜態(tài)庫中一般包含代碼文件和資源文件
? ? 代碼文件:OC類的.h和.m文件、OC分類文件(Category文件)、C文件、C++文件等
????資源文件:代碼文件需要調(diào)用的資源,如圖片、xib文件、plist文件等
????生成的靜態(tài)庫文件中如果包含有除OC類的.h和.m代碼文件文件外,還有OC分類文件、C文件、C++文件,在導(dǎo)入該靜態(tài)庫時需要在Xcode->Build Settings->Other Linker Flags進行特殊設(shè)置;包含OC分類需要將Other Linker Flags設(shè)置為-ObjC;包含OC分類、C文件、C++文件需要添加-all_load;包含OC分類、C文件、C++文件,也可將Other Linker Flags設(shè)置為-force_load。
???在iOS中,代碼庫中對資源文件進行管理,都是使用Bundle文件;所以如果生成的靜態(tài)庫文件中包含資源文件,需要為代碼庫創(chuàng)建一個Bundle文件,對代碼庫中的資源文件進行統(tǒng)一管理。
????2.Other Linker Flags標記值的說明
? ? -ObjC:Unix的標準靜態(tài)庫實現(xiàn)和Objective-C的動態(tài)特性之間有一些沖突:Objective-C沒有為每個函數(shù)(或者方法)定義鏈接符號,它只為每個類創(chuàng)建鏈接符號。這樣當在一個靜態(tài)庫中使用分類來擴展已有類的時候,鏈接器不知道如何把類原有的方法和分類中的方法進行關(guān)聯(lián),就會導(dǎo)致你調(diào)用分類中的方法時,出現(xiàn)”selector not recognized”,也就是找不到方法定義的錯誤。為了解決這個問題,引入了-ObjC標志,它的作用就是將靜態(tài)庫中所有的和對象相關(guān)的文件都加載進來。
? ? -all_load:可以強制加載所有的OC分類、C文件、C++文件。該標記值是專門處理-ObjC的一個bug的。用了-ObjC以后,如果類庫中只有category沒有類的時候這些category還是加載不進來。
? ? -force_load:可以強制加載所有的OC分類、C文件、C++文件,但是-force_load后面必須跟一個指向該.a文件的靜態(tài)庫路徑。
????當靜態(tài)庫使用以上加載標記值時,這樣會導(dǎo)致編譯之后的app會變大(因為加載了其它的代碼進來);但是如果靜態(tài)庫中有OC分類文件、C文件、C++文件的話只有加入對應(yīng)的標記值才能編譯通過。
(五)簡單.a靜態(tài)庫的生成和使用
1.以Xcode9.2為例,創(chuàng)建.a靜態(tài)庫工程

2.設(shè)置.a靜態(tài)庫
? ??Supported Platforms選項設(shè)置為iOS及為適用手機平臺的.a,也可為macOS及適用Mac電腦平臺的.a等。
? ??Valid Architectures設(shè)置兼容的設(shè)備類型,詳情見:iOS中設(shè)備的分類。

3.自定義需要的類和方法

4.設(shè)置.a文件的環(huán)境模式、路徑和可見的文件
? ? Edit Scheme設(shè)置.a環(huán)境模式,我這里以Debug模式為例。

Subpath設(shè)置可見文件的子路徑,下圖為默認路徑;$(PRODUCT_NAME)為工程名稱。
name下的文件為生成.a靜態(tài)庫中可見的文件,將對應(yīng)的.m文件可見可以在導(dǎo)入該.a文件中對對應(yīng)的方法進行修改。

5.生成.a文件
? ? 選擇任意一個模擬器,command+b生成debug模式下調(diào)試環(huán)境的.a文件。
? ? 選擇Generic iOS Device,command+b生成debug模式下發(fā)布環(huán)境的.a文件。

? ??Debug-iphonesimulator文件夾是調(diào)試環(huán)境下的.a文件,Debug-iphoneos文件夾是發(fā)布環(huán)境下的.a文件。

6.查看.a文件編譯環(huán)境:
(cd .a文件所在的文件夾)命令進入.a所在的文件夾,用(lipo -info .a文件名)命令查看.a文件編譯環(huán)境

7.合并調(diào)試環(huán)境和發(fā)布環(huán)境下的.a文件
????將調(diào)試環(huán)境和發(fā)布環(huán)境.a文件重命名并復(fù)制到合成.a文件所在的文件夾。(cd 合成.a文件所在的文件夾)命令進入.a所在的文件夾,用(lipo -create .a文件名 .a文件名 -output 合成.a文件名)命令合成所得.a文件
8.在工程中使用.a文件
? ? 在工程中導(dǎo)入.h文件夾和.a文件。

在工程中需要調(diào)用.a庫中的文件中,導(dǎo)入頭文件,代碼中調(diào)用.a中封裝的方法。如果.a中對應(yīng)的方法的.m文件也可訪問,可以在.m中修改該代碼的實現(xiàn)。

? ? 注意:在模擬器環(huán)境下及調(diào)試環(huán)境下和在真機環(huán)境下及發(fā)布環(huán)境下,必須導(dǎo)入對應(yīng)的.a文件或者合成兩環(huán)境下的.a文件,否則會出錯,導(dǎo)致工程編譯失敗。