一曲横、簡(jiǎn)介
I. 庫(kù)的類型分類
靜態(tài)庫(kù)
- 以
.a
或.framework
為文件后綴名
.a
是一個(gè)二進(jìn)制文件,不能直接拿來(lái)用榨乎,使用時(shí)需要.a
文件 + 頭文件 + 資源文件
靜態(tài)庫(kù)打包時(shí),只能打包代碼,圖片文件县爬、本地 JSON 文件和 xib 等資源文件無(wú)法打包進(jìn)去 - 靜態(tài)庫(kù) 連接時(shí) 完整的復(fù)制到可執(zhí)行文件中,多個(gè)文件使用添谊,多份拷貝
- OC 建議使用靜態(tài)庫(kù)财喳,OC 使用動(dòng)態(tài)庫(kù)審核可能會(huì)不通過(guò)
- 靜態(tài)庫(kù)無(wú)法再包含其他的 .a 靜態(tài)庫(kù)。只能把源碼放進(jìn)去一起編譯
動(dòng)態(tài)庫(kù)
- 以
.dylib
或.framework
為文件后綴名「Xcode7 后.dylib
變?yōu)?.tbd
文件」
.framework
文件斩狱,能直接拿來(lái)用耳高。.framework
文件 = 二進(jìn)制文件(.a 文件 + .h 文件) + 資源文件
.tbd
文件,只是一個(gè)文本文件所踊,其中包含架構(gòu)信息泌枪,以及在真實(shí)運(yùn)行時(shí)候二進(jìn)制所在的位置,以及包含了動(dòng)態(tài)庫(kù)的符號(hào)表還有類的一些信息秕岛,這些信息在編譯階段足夠了碌燕∥笾ぃ「減少了所有設(shè)備 SDK 二進(jìn)制動(dòng)態(tài)庫(kù)的體積」 - 動(dòng)態(tài)庫(kù) 運(yùn)行時(shí) 動(dòng)態(tài)加載到內(nèi)存,只加載一次修壕,多個(gè)文件公用愈捅,節(jié)省內(nèi)存
- Swift 只能使用動(dòng)態(tài)庫(kù),不支持靜態(tài)庫(kù)
- 大部分第三方庫(kù)就是動(dòng)態(tài)庫(kù)慈鸠,可以暴露出來(lái)蓝谨,放在源碼的外部引用使用
- 動(dòng)態(tài)庫(kù)的特性使得軟件版本實(shí)時(shí)模塊升級(jí)、應(yīng)用插件化青团、etc
II. iOS 設(shè)備的 CPU 架構(gòu)
iOS 庫(kù)的打包譬巫,根據(jù) CPU 架構(gòu)的不同而不同
架構(gòu)不同,不能編譯通過(guò)
模擬器的 CPU 架構(gòu)
- i386:iPhone 4s ~ 5
- x86_64:iPhone 5s ~ 7 Plus
真機(jī)的 CPU 架構(gòu)
- 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)庫(kù)只要支持了 armv7记罚,就可以在 armv7s 的架構(gòu)上運(yùn)行」
- armv64:iPhone 5s墅诡、iPhone 6、iPhone 6 Plus桐智、iPhone 6s末早、iPhone 6s Plus、iPad Air说庭、iPad Air2然磷、iPad mini2、iPad mini3
二刊驴、打包靜態(tài)庫(kù)
I. .a 文件 靜態(tài)庫(kù)打包
- 創(chuàng)建靜態(tài)庫(kù)的工程
創(chuàng)建后執(zhí)行 運(yùn)行 或 編譯 姿搜,都可以生成靜態(tài)庫(kù)「保存在項(xiàng)目的Products
中」
- 通過(guò)在不同架構(gòu)的設(shè)備下 編譯/運(yùn)行 生成支持不同架構(gòu)的靜態(tài)庫(kù)
- 在 編譯/運(yùn)行 時(shí),所有項(xiàng)目 都可以設(shè)置是 Debug 還是 Release
- 設(shè)置庫(kù)的接口 頭文件
- 通過(guò)設(shè)置不僅在當(dāng)前運(yùn)行的 CPU 架構(gòu)上捆憎,適配所有的機(jī)型號(hào)架構(gòu)
一般 debug = no舅柜,release = yes 為了 debug 的時(shí)候編譯更快「只編譯連接當(dāng)前的 CPU 架構(gòu)所用的包」
可以控制 測(cè)試版本 和 發(fā)布版本 是否都不僅僅能在真機(jī)上使用
II. .framework 文件 靜態(tài)庫(kù)打包
- 前三步和 在 .a 文件 打包方式一致
- 設(shè)置庫(kù)的接口 頭文件
- 設(shè)置打包的是 靜態(tài)庫(kù),因?yàn)閯?dòng)態(tài)庫(kù)也可以以 framework 的形式存在
設(shè)為Static Library「這個(gè)默認(rèn)選項(xiàng)是動(dòng)態(tài)的」
III. 使用靜態(tài)庫(kù)
1. 防止項(xiàng)目中的文件和 靜態(tài)庫(kù)的同名文件在運(yùn)行時(shí)會(huì)覆蓋躲惰,只保留一張圖片
- 把圖片文件單獨(dú)的放在一個(gè) .bundle 文件中「一般 .bundle 的名字和
.a
或.framework
的名字相同」 - .bundle 文件制作方法:將文件夾致份,重命名為 XXX.bundle
同理,其他資源文件也放在一個(gè) .bundle 中
2. 在使用 category 靜態(tài)庫(kù)的工程中础拨,調(diào)用方法時(shí)知举,會(huì)出現(xiàn)找不到該方法的運(yùn)行時(shí)錯(cuò)誤:selector not recognized
原因:
- Unix 的標(biāo)準(zhǔn)靜態(tài)庫(kù)實(shí)現(xiàn)和 Objective-C 的動(dòng)態(tài)特性之間有一些沖突
- Objective-C 沒(méi)有為每個(gè)函數(shù)定義鏈接符號(hào)瞬沦,它只為每個(gè)類創(chuàng)建鏈接符號(hào)
- 當(dāng)在一個(gè)靜態(tài)庫(kù)中使用類別來(lái)擴(kuò)展已有類的時(shí)候,鏈接器不知道如何把類原有的方法和類別中的方法整合起來(lái)
解決辦法:
- 在使用靜態(tài)庫(kù)的工程中配置
other linkerflags
的值為-ObjC
如果還崩潰雇锡,在添加-all_load
「或者-force_load
」 - all_load 作用于所有的庫(kù),而 -force_load 后面必須要指定具體的文件
這樣僚焦,會(huì)將靜態(tài)庫(kù)中所有和對(duì)象相關(guān)的文件都加載進(jìn)來(lái)
3. 避免暴露過(guò)多的 .h 文件
使用
- 在靜態(tài)庫(kù)的內(nèi)部創(chuàng)建一個(gè) .h 文件「一般這個(gè).h文件的名字和靜態(tài)庫(kù)的名字相同」
然后把所有需要暴露出來(lái)的 .h 文件名都集中放在這個(gè) .h 文件中锰提,只需要把這個(gè) .h 暴露出來(lái) - 一般這個(gè)總頭文件內(nèi)部引入其他頭文件的格式為
#import <framework名字/其他頭文件.h>
,這是以調(diào)用這個(gè)庫(kù)的項(xiàng)目的角度來(lái)寫(xiě)的
搜索頭文件
Header Search Paths
系統(tǒng)的搜索路徑芳悲,用來(lái)引入項(xiàng)目中沒(méi)有添加的 header 文件
通過(guò)#import <名稱.h>
來(lái)引入User Header Search Paths
用戶的搜索路徑立肘,用來(lái)引入項(xiàng)目中的已添加的 header 文件
通過(guò)#import <名稱.h>
或#import "名稱.h"
來(lái)引入Always Search User Paths
Header Search Paths 作為系統(tǒng)級(jí)別路徑一定會(huì)被搜索
設(shè) Always Search User Paths 為 YES,編譯器會(huì)先搜索 User Header Search Paths 路徑下的目錄
設(shè) Always Search User Paths 為 NO名扛,編譯器不會(huì)搜索 User Header Search Paths 路徑下的目錄「默認(rèn)」設(shè)置格式舉例:
$(SRCROOT)/項(xiàng)目名稱/AppDelegate.h
$(SRCROOT)
宏和$(PROJECT_DIR)
宏都指 xxx.xcodeproj 所在的父目錄谅年,新建項(xiàng)目后的目錄為:
Project 的 Building Settings 中得設(shè)置默認(rèn)并不被 Targets 繼承
只有 Targets 的設(shè)置加入了$(inherited)
時(shí)才被繼承,添加目錄的時(shí)候?qū)懮?$(inherited)
就表示從 frameworks 里面讀取設(shè)置查找路徑的參數(shù)
recursive:遍歷該目錄肮韧,編譯的時(shí)候在找?guī)斓穆窂降臅r(shí)候融蹂,會(huì)遍歷該目錄下的所有子目錄的庫(kù)文件
non-recursive:不遍歷該目錄「默認(rèn),推薦使用弄企,可減少編譯速度」
4. 拖拽項(xiàng)目/將項(xiàng)目當(dāng)做靜態(tài)庫(kù)處理
- 給當(dāng)前項(xiàng)目在
Link Binary With Libraries
中添加拖拽項(xiàng)目的 庫(kù)文件 - 如果當(dāng)前的 Target 需要依賴其他庫(kù)文件超燃,在
Target Dependencies
中添加所需的庫(kù)文件 - 如果庫(kù)文件在
Link Binary With Libraries
中已經(jīng)添加「必要」,但也可能需要在Target Dependencies
中再次添加「非必要」
5. 其他
查看靜態(tài)庫(kù)所支持的 CPU 架構(gòu)
在命令行找到靜態(tài)庫(kù)所在的文件夾拘领,執(zhí)行lipo -info 靜態(tài)庫(kù)文件名
命令合并靜態(tài)庫(kù)
在命令行找到靜態(tài)庫(kù)所在的文件夾意乓,執(zhí)行lipo -create 靜態(tài)庫(kù)1 靜態(tài)庫(kù)2 -output 新靜態(tài)庫(kù)名稱.a
命令
三、打包動(dòng)態(tài)庫(kù)
1. 制作约素、編譯過(guò)程與靜態(tài)庫(kù)相同
2. 在 Embedded Binaries
中添加動(dòng)態(tài)庫(kù)
3. 合并動(dòng)態(tài)庫(kù)文件
合并動(dòng)態(tài)庫(kù)文件并非合并的是 .framework
文件届良,而是其中的二進(jìn)制代碼文件
4. 動(dòng)態(tài)庫(kù)的使用注意
I. 自定義的 .a
靜態(tài)庫(kù),不可以包含動(dòng)態(tài)庫(kù)
II. 自定義的 .framework
靜態(tài)庫(kù)圣猎,可以包含動(dòng)態(tài)庫(kù)文件
繞過(guò) Xcode 的 UI 界面來(lái)連接動(dòng)態(tài)庫(kù)士葫,步驟如下
- 項(xiàng)目中不需要引用連接的動(dòng)態(tài)庫(kù)「.tbd 的動(dòng)態(tài)庫(kù)」
- 通過(guò)格式:
-l<library_name>
添加動(dòng)態(tài)庫(kù),例:添加libiconv.tdb
記為-liconv
缺陷
- 雖然自定義的靜態(tài)庫(kù)中已經(jīng)導(dǎo)入了動(dòng)態(tài)庫(kù) X.tbd 样漆,但是为障,當(dāng)自定義的 framework 的靜態(tài)庫(kù)被調(diào)用時(shí),可能需要再次導(dǎo)入動(dòng)態(tài)庫(kù) X.tbd 到當(dāng)前項(xiàng)目中