轉(zhuǎn)載請(qǐng)注明出處:
http://www.lxweimin.com/p/04a7e28f11b9
作者:紀(jì)小衰
framework的使用十分方便,一般來說直接拖入到項(xiàng)目中就可以直接使用接口,而不用在意具體的實(shí)現(xiàn)細(xì)節(jié),對(duì)于功能的封裝是個(gè)很好的途徑。當(dāng)我們寫的工具給別人使用的同時(shí)又不想讓別人知道自己的代碼,這個(gè)時(shí)候使用framework就可以派上用場(chǎng)了(ps:個(gè)人覺得開源是一個(gè)大牛必須要體會(huì)到的思想)。。。
廢話不多說,xcode如今已經(jīng)到了7,對(duì)于framework的制作可以說是十分方便了。公司之前的framework的制作都是采用執(zhí)行純腳本的方法,可以直接命令行編譯和融合不同版本(模擬器,真機(jī),debug,release)的framework,個(gè)人不是很喜歡,還是喜歡用較為官方的方式來制作framework,當(dāng)然為了方便還是少量地參照了網(wǎng)上的一些腳本。
一、新建framework工程
xcode->file->new->project選中iOS下的cocoa touch framework->next
接下來的步驟和創(chuàng)建一個(gè)普通的工程沒什么區(qū)別,創(chuàng)建完畢以后在工程中新建JRModel類和JRModel2類文件,在我們的framework工程創(chuàng)建以后系統(tǒng)會(huì)默認(rèn)創(chuàng)建一個(gè)和工程名相同的頭文件,我這里是JRDataModel.h。一般來說我們會(huì)把framework中需要提供給外部的頭文件都在這個(gè)頭文件中import一下,這樣使用者只要包含一個(gè)頭文件就可以使用所有的類了。
這個(gè)地方需要注意到兩點(diǎn),一個(gè)就是導(dǎo)入的時(shí)候必須要使用framework的方式導(dǎo)入,使用<包名/頭文件名.h>,因?yàn)樵趯?shí)際使用framework的時(shí)候是需要從包中搜索頭文件的。還有一個(gè)坑就是右邊的那個(gè)設(shè)置,對(duì)于總的頭文件還有所有需要用到的頭文件,都需要公開,選中以后把右邊包的編譯屬性改為public,否則打出來的包在別的工程中實(shí)際上是不能引用的。
二、編譯工程
接下來就是開始編譯工程了(如下圖),選中運(yùn)行按鈕右邊的編譯目標(biāo),選擇Generic iOS Device,然后command+b編譯一下,這個(gè)時(shí)候我們工程中的products文件夾下面的framework文件會(huì)由原來的紅色(表示文件丟失)變成黑色(表示文件存在)。如果我們選擇的是Generic iOS Device那么編譯出來的framework只能在真機(jī)中使用,如果選中的是普通的模擬器,那么編譯出來framewo只能在模擬器中使用。
tips:這里需要注意一下,如果一開始選擇的是模擬器,那么即使build成功,framework也不會(huì)變成黑色,可能是因?yàn)檫@里的framework指向的是真機(jī)中對(duì)應(yīng)的framework,但是在相對(duì)應(yīng)的目錄下的模擬器對(duì)應(yīng)的framework是存在的
右擊生成好的framework,選中show in finder可以查看framework在磁盤中的位置。進(jìn)入目錄以后,一般來說最多有四個(gè)目錄,我這里只有三個(gè)(如下圖)因?yàn)閷?duì)于模擬器一般不會(huì)要release版本的。也可以通過finder,快捷鍵control+command+g輸入~/Library/Developer/Xcode/DerivedData/Build/Products默認(rèn)路徑進(jìn)入
分別在模擬器和真機(jī)選項(xiàng)中編譯,發(fā)現(xiàn)實(shí)際只產(chǎn)生了模擬器和真機(jī)的debug版本的framework包,而沒有release版本的包。這需要我們調(diào)整一下xcode的build類型,選中運(yùn)行的target在下來列表中選Edit Scheme,進(jìn)入以后把run中的Build Configureation修改為Release,這時(shí)候就可以編譯出release版本的包了(如下圖)
三、合并framework
到此,我們已經(jīng)制作出對(duì)于各種情況下使用的framework了,對(duì)于不同的環(huán)境需要使用不同種類的framework,這在很多時(shí)候顯得很麻煩。能不能制作一個(gè)能在所有場(chǎng)景使用的包呢。
這個(gè)時(shí)候我們可以考慮合并所有版本的包,一般來說可以使用腳本進(jìn)行合并,但是每次使用腳本比較麻煩,我們可以在xcode中添加一個(gè)共同體aggregate,然后添加編譯腳本來實(shí)現(xiàn)。
在工程中點(diǎn)擊上方工具欄File->New->Target,在選項(xiàng)中選擇Other中的Aggregate,命名最好和工程名有關(guān),我這里就寫成JRDataModelAggregate。
新建好以后,選擇targets列表下的JRDataModelAggregate,點(diǎn)擊build phases,點(diǎn)擊+新建一個(gè)New Run Script Phase,把下面的腳本復(fù)制到shell下的選項(xiàng)中(腳本來源自網(wǎng)絡(luò),感謝這段腳本的原作者)。有能力的可以根據(jù)自己的需要修改下面的腳本。
# Sets the target folders and the final framework product.
#如果工程名稱和Framework的Target名稱不一樣的話,要自定義FMKNAME
#例如: FMK_NAME = "MyFramework"
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}"
復(fù)制完以后,點(diǎn)擊左上角運(yùn)行旁邊的target(上圖左上角那個(gè)黃色的選項(xiàng)),在下拉的列表中選中我們剛才創(chuàng)建的JRDataModelAggregate,command+B編譯一下,如果沒什么意外,等到編譯成功便會(huì)彈出我們編譯好的framework了。
四、驗(yàn)證framework
framework其實(shí)可以看做是一個(gè)帶擴(kuò)展名的文件夾,所以我們可以直接進(jìn)入framework的內(nèi)部。通過下面的控制臺(tái)指令進(jìn)入到framework中(cd后面是你自己的framework路徑)
cd /Users/ctzxh/Desktop/JRModel/JRDataModel/Products/JRDataModel.framework
執(zhí)行下面的命令判斷當(dāng)前framework支持的架構(gòu)
lipo -info JRDataModel
Tips1:
對(duì)于上面的每種處理器架構(gòu)對(duì)應(yīng)的設(shè)備請(qǐng)自行百度。這里說明一下,如果讓你的包可以支持armv7s的架構(gòu)(這里說的支持指的是針對(duì)這種架構(gòu)的優(yōu)化),可以根據(jù)下圖的方式添加,新版的xcode默認(rèn)便沒有加上armv7s的架構(gòu),由于處理器向下兼容,所以即使不添加,所使用包的工程也是可以在armv7s架構(gòu)上的機(jī)器運(yùn)行的。個(gè)人推薦還是不必考慮了,按照官方的來就可以了。添加完以后在驗(yàn)證包的時(shí)候會(huì)多顯示一個(gè)armv7s。
Tips2:
上面用Aggregate制作的庫(kù)是拖入到使用的工程是直接可以使用的,但是之前分別制作的庫(kù)直接拖入是不能使用的,解決的方式有兩種:
第一種:制作鏈接庫(kù)的時(shí)候,選擇生成靜態(tài)庫(kù)
第二種:在使用動(dòng)態(tài)鏈接庫(kù)的時(shí)候嵌入二進(jìn)制庫(kù),在下面的選項(xiàng)中添加要導(dǎo)入的動(dòng)態(tài)庫(kù)
網(wǎng)上有種方式是把framework的屬性從required變成Optional,親測(cè)行不通,能導(dǎo)入但是不能用。。。
就到這兒吧~~~
Add:如果只做的是.a的靜態(tài)庫(kù)可以使用下面的腳本,方法一樣
if["${ACTION}"="build"]
then
#要build的target名
target_Name=${PROJECT_NAME}
echo"target_Name=${target_Name}"
#build之后的文件夾路徑
build_DIR=${SRCROOT}/build
echo"build_DIR=${build_DIR}"
#真機(jī)build生成的頭文件的文件夾路徑
DEVICE_DIR_INCLUDE=${build_DIR}/Release-iphoneos/include/${PROJECT_NAME}
echo"DEVICE_DIR_INCLUDE=${DEVICE_DIR_INCLUDE}"
#真機(jī)build生成的.a文件路徑
DEVICE_DIR_A=${build_DIR}/Release-iphoneos/lib${PROJECT_NAME}.a
echo"DEVICE_DIR_A=${DEVICE_DIR_A}"
#模擬器build生成的.a文件路徑
SIMULATOR_DIR_A=${build_DIR}/Release-iphonesimulator/lib${PROJECT_NAME}.a
echo"SIMULATOR_DIR_A=${SIMULATOR_DIR_A}"
#目標(biāo)文件夾路徑
INSTALL_DIR=${SRCROOT}/Products/${PROJECT_NAME}
echo"INSTALL_DIR=${INSTALL_DIR}"
#目標(biāo)頭文件文件夾路徑
INSTALL_DIR_Headers=${SRCROOT}/Products/${PROJECT_NAME}/Headers
echo"INSTALL_DIR_Headers=${INSTALL_DIR_Headers}"
#目標(biāo).a路徑
INSTALL_DIR_A=${SRCROOT}/Products/${PROJECT_NAME}/lib${PROJECT_NAME}.a
echo"INSTALL_DIR_A=${INSTALL_DIR_A}"
#判斷build文件夾是否存在,存在則刪除
if[ -d"${build_DIR}"]
then
rm -rf"${build_DIR}"
fi
#判斷目標(biāo)文件夾是否存在,存在則刪除該文件夾
if[ -d"${INSTALL_DIR}"]
then
rm -rf"${INSTALL_DIR}"
fi
#創(chuàng)建目標(biāo)文件夾
mkdir -p"${INSTALL_DIR}"
#build之前clean一下
xcodebuild -target${target_Name}clean
#模擬器build
xcodebuild -target${target_Name}-configuration Release -sdk iphonesimulator
#真機(jī)build
xcodebuild -target${target_Name}-configuration Release -sdk iphoneos
#復(fù)制頭文件到目標(biāo)文件夾
cp -R"${DEVICE_DIR_INCLUDE}""${INSTALL_DIR_Headers}"
#合成模擬器和真機(jī).a包
lipo -create"${DEVICE_DIR_A}""${SIMULATOR_DIR_A}"-output"${INSTALL_DIR_A}"
#打開目標(biāo)文件夾
open"${INSTALL_DIR}"
fi