制作靜態(tài)庫
- 動(dòng)態(tài)庫:
.dylib
.framework
- 靜態(tài)庫:
.a
.framework
兩者區(qū)別*:動(dòng)態(tài)庫時(shí)在程序運(yùn)行時(shí)動(dòng)態(tài)鏈接的,且可以被多個(gè)程序鏈接,相當(dāng)于以動(dòng)態(tài)庫為中心,系統(tǒng)只會(huì)加載動(dòng)態(tài)庫到內(nèi)存一次氓栈,這樣動(dòng)態(tài)庫就始終只占一份內(nèi)存,而靜態(tài)庫是提前把需要編譯的實(shí)現(xiàn)文件編譯為二進(jìn)制文件,每個(gè)程序都需要復(fù)制一份创夜,這是在使用靜態(tài)庫就決定了的特性,我們需要把靜態(tài)庫復(fù)制到工程文件內(nèi)仙逻,供我們程序使用驰吓,而在制作時(shí)靜態(tài)庫時(shí),我們可以選擇暴露哪些文件給使用者系奉,當(dāng)然大部分都只需暴露頭文件檬贰,我們當(dāng)然也可以暴露實(shí)現(xiàn)文件,供我們參考學(xué)習(xí)缺亮,了解其中原理翁涤,眾使我們修改了該文件的內(nèi)容也沒關(guān)系,因?yàn)樵撐募呀?jīng)在制作靜態(tài)庫時(shí)已經(jīng)編譯成二進(jìn)制文件萌踱,我們使用時(shí)不會(huì)再次編譯該文件葵礼,資源文件如圖片等也是可以我們替換,因?yàn)榫幾g時(shí)只是簡單的COPY并鸵,所以我們可以替換SVProgressHUB
里的error或success成我們個(gè)性化的圖片鸳粉。蘋果官方不允許我們App包含動(dòng)態(tài)庫。
.a
與.framework
的區(qū)別:
制作.a
都需要我們手動(dòng)在Header Search Paths
加頭文件搜索路徑
制作 .framework
不需要
制作.framework
靜態(tài)庫
我們先說.framework
的制作過程能真,我們新建項(xiàng)目選擇iOS的framwork / library 赁严,建好后默認(rèn)有一個(gè)頭文件扰柠,這不是我們需要的,直接刪掉疼约,這里我們可以任意建文件夾和文件卤档,把我們需要的功能庫搭建好后,我們在Build phase > Headers > public 內(nèi)添加我們需要暴露的文件程剥,這樣我們就建好了劝枣,然后我們分別選著模擬器 和 Generic iOS Device
來構(gòu)建我們的product ,只有當(dāng)我們構(gòu)建完Generic iOS Device
才能看到product內(nèi)的target由紅色變?yōu)楹谏ǎ@說明文件存在舔腾,構(gòu)建完畢,然后我們右鍵 show in finder
找到編譯好的文件搂擦,當(dāng)然稳诚,這個(gè)文件只包含armv7 和arm64 架構(gòu)的。我們還需要在Mach-type
修改類型為Static Library
,當(dāng)然我們也可以制作動(dòng)態(tài)庫瀑踢,只是不能發(fā)布扳还。如果你制作動(dòng)態(tài)庫就需要在Embedded Binaries
內(nèi)添加庫。
對于這幾種CPU架構(gòu)分類:
真機(jī):
3gs ~ 4s :armv7
5 ~5c :armv7s
5s~ 6plus:arm64
模擬器:
4s~5 : i386
5s~6plus : x86_64
所以我們需要合并這幾種包橱夭,并且都是debug包氨距,我們一般發(fā)布給別人Release包,這需要我們Edit Scheme 選擇Run > info >build configuration 為Release棘劣。Release包會(huì)比debug包要小一點(diǎn)俏让,因?yàn)榫幾g時(shí)作了代碼優(yōu)化,運(yùn)行效率會(huì)高一點(diǎn)茬暇,但不會(huì)明顯提高首昔。
為了保證都能運(yùn)行,我們還需要合并包而钞,這里的包是.framework
文件里的同名的無擴(kuò)展名的二進(jìn)制文件沙廉,使用下面命令合并,更多使用方法( man lipo
)
lipo -create test1 test2 -output test3
然后替換之前任意一個(gè)同名的二進(jìn)制文件臼节,這里多次強(qiáng)調(diào)同名撬陵,因?yàn)橄到y(tǒng)就是根據(jù)根據(jù)靜態(tài)庫名在靜態(tài)庫內(nèi)尋找二進(jìn)制文件,不然會(huì)報(bào)找不到該文件的錯(cuò)誤网缝。
這樣我們直接把替換二進(jìn)制文件后的.framework
文件拖進(jìn)我們其它工程直接使用巨税。
當(dāng)然如果我們還需要在靜態(tài)庫內(nèi)使用資源文件,我們使用Bundle粉臊,在該項(xiàng)目內(nèi)Add Target 草添,選擇OSX 內(nèi)的Bundle,我們需要?jiǎng)h除一系列扼仲,修改sdk远寸,修改product name等等抄淑。
制作.a
靜態(tài)庫
類似制作.framework
靜態(tài)庫,我們新建項(xiàng)目XHQ_StaticFramework
驰后,選擇Cocoa Touch Static Library
這時(shí)可以看到兩個(gè)文件夾:XHQ_StaticFramework
和Product
, Xcode 為我們自動(dòng)建好的XHQ_StaticFramework(.h/.m)
文件肆资,一般我們只需要頭文件,頭文件寫下我們所有需要公開的頭文件灶芝,其它全部刪掉郑原,以便客戶使用時(shí)只需引入這個(gè)頭文件。Product存放我們生成的二進(jìn)制文件夜涕。這里我們引入<UIKit/UiKit.h>框架犯犁,(網(wǎng)上多個(gè)版本都提到需要在Build Phrases >Link Binary With Libraries
內(nèi)添加UIKit.framework
,但是作者沒有添加也能正常使用,如果你知道原因請告訴我女器,謝謝K嵋邸)
我們在XHQ_StaticFramework
文件夾下建好我們自己的代碼庫后,把需要公開的頭文件加到Build Phases >Headers
晓避,如果你沒有這個(gè)目錄簇捍,你需要手動(dòng)Editor > Add Build Phases> Add Headers Build Phases
來添加。(提示:如果無法選擇俏拱,你需要點(diǎn)擊Build Phases 空白處后再重復(fù)上面的步驟。)
點(diǎn)開 Headers 默認(rèn)是有三個(gè)文件目錄: public&&private&&project
, 其中pulic和private都是放對外公開的文件吼句,兩者區(qū)別就是存儲(chǔ)的路徑可能不一樣锅必,我們可以在Packaging> Private/Public Headers Folder Path
設(shè)置路徑。這里我們設(shè)置為include/$(PROJECT_NAME)
,project
存放我們私有的文件惕艳。
然后我們需要在Build Settings
設(shè)置一些值:
Dead Code Stripping > NO(去掉不會(huì)執(zhí)行到的代碼)
Strip Style > Debugging Symbols
Strip Debug Symbol During Copy > NO(去掉Debug相關(guān)符號(hào))
Strip Linked Product > NO
這樣做是為了后期產(chǎn)生bug時(shí)搞隐,我們能通過符號(hào)文件定位到我們需要的類的信息, 但是如果是iOS 或者 OSX則配置完全相反。相關(guān)文章
我們編譯成功后就可以正常使用远搪。使用時(shí)我們有兩種方式
一種是在其它項(xiàng)目中拖進(jìn)該項(xiàng)目劣纲,在新項(xiàng)目中添加依賴
Build Phases > Target Dependencies
添加.a
靜態(tài)庫,然后就是link library
內(nèi)添加.a
靜態(tài)庫;
上面的方式適合我們自己內(nèi)部使用谁鳍,好處就是可以動(dòng)態(tài)的修改靜態(tài)庫的文件癞季,Xcode會(huì)根據(jù)是否需要重新編譯來生成靜態(tài)文件,而其實(shí)我們可以是直接使用生成的
.a
靜態(tài)庫和包涵頭文件的include文件夾倘潜,只不過我們每次都需要配置Search Headers Paths绷柒,這種方式適合給外部使用。
使用腳本生成集成包
相信上面的這些分別生成支持不同架構(gòu)的包已經(jīng)讓你精疲力竭涮因,我們有更加方便的方法制作通用的包废睦,那就是使用腳本來構(gòu)建支持多個(gè)架構(gòu)的包.首先我們在前面制作framework的基礎(chǔ)上添加
Aggragate
target,然后在Build Phases
內(nèi)添加 Run Script
把下面代碼添加進(jìn)去养泡。直接運(yùn)行嗜湃,然后生成的包目錄會(huì)自動(dòng)打開奈应。
FMK_NAME=${PROJECT_NAME}
# Install dir will be the final output to the framework.
# The following line create it in the root folder of the current project.
INSTALL_DIR=${SRCROOT}/Products/${FMK_NAME}.framework
# Working dir will be deleted after the framework creation.
WRK_DIR=build
DEVICE_DIR=${WRK_DIR}/Release-iphoneos/${FMK_NAME}.framework
SIMULATOR_DIR=${WRK_DIR}/Release-iphonesimulator/${FMK_NAME}.framework
# -configuration ${CONFIGURATION}
# Clean and Building both architectures.
xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphoneos clean build
xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphonesimulator clean build
# Cleaning the oldest.
if [ -d "${INSTALL_DIR}" ];then
rm -rf "${INSTALL_DIR}"
fi
mkdir -p "${INSTALL_DIR}"
cp -R "${DEVICE_DIR}/" "${INSTALL_DIR}/"
# Uses the Lipo Tool to merge both binary files (i386 + armv6/armv7) into one Universal final product.
lipo -create "${DEVICE_DIR}/${FMK_NAME}" "${SIMULATOR_DIR}/${FMK_NAME}" -output "${INSTALL_DIR}/${FMK_NAME}"
rm -r "${WRK_DIR}"
open "${INSTALL_DIR}"