公司最近要開發(fā)一個(gè)SDK,不知如何下手,請教了一個(gè)有SDK開發(fā)經(jīng)驗(yàn)的同事剥槐,也在網(wǎng)上查了些資料,決定整理一下宪摧。整體上講就是在SVN上創(chuàng)建一個(gè)項(xiàng)目路徑才沧,再用Xcode創(chuàng)建一個(gè)項(xiàng)目工程迈喉,把項(xiàng)目工程上傳到SVN上就可以開發(fā)了剃根,這里只討論項(xiàng)目工程的創(chuàng)建盗飒。
一妇汗、創(chuàng)建一個(gè)workspace
1、在桌面上創(chuàng)建一個(gè)文件夾MyTestSDK(名字自己人昵浮)
2、打開Xcode,創(chuàng)建一個(gè)workspace,路徑放到文件夾MyTestSDK里面膝蜈,Xcode---File---New---Workspace
之后可以看到MyTestSDK文件夾里面多了一個(gè).xcworkspace文件
二锅移、創(chuàng)建SDK
1、打開MyTestSDK.xcworkspace文件饱搏,創(chuàng)建project
選擇Cocoa Touch Framework
把framework添加到workspace里面
添加之后的效果圖
三非剃、創(chuàng)建Demo
1、打開MyTestSDK.xcworkspace文件推沸,創(chuàng)建project
2备绽、選擇Single View Application
3、添加application到workspace
最終效果圖
從上圖可以看出鬓催,上面是demo肺素,下面是sdk,怎么把這兩者關(guān)聯(lián)起來呢宇驾?倍靡??课舍?塌西??筝尾?捡需?
四、Demo的關(guān)聯(lián)以及SDK的開發(fā)調(diào)試
1忿等、把SDK打包成framework
這個(gè)步驟網(wǎng)上有很多種教程栖忠,最后可以手動(dòng)生成framework也可以用腳本生成framework,這里就以腳本生成framework為例贸街,其他方法有興趣的同學(xué)可以自己研究
參考:qingmang.me/articles/5162103427194116731/
這里創(chuàng)建一個(gè)MyView類庵寞,繼承于UIView,簡單的重寫了初始化方法薛匪,設(shè)置了顏色
設(shè)置Build Setting參數(shù)
更改參數(shù)捐川,在Architectures下增加armv7s(iOS11上不支持armv7s,如果報(bào)錯(cuò)就不要添加),并選中逸尖。將Build Active Architecture only設(shè)置為NO
設(shè)置Headers古沥,將要公開的頭文件拖到Public下瘸右,要隱藏的放到Private或Project下,隱藏的頭文件不能被引用
然后需要在MyTestSDK.h(必須是公開的岩齿,否則無法引用)中將所有要公開的.h引入
創(chuàng)建一個(gè)Aggregare
嵌入腳本太颤,選中剛剛創(chuàng)建的Aggregare,然后選中右側(cè)的Build Phases,點(diǎn)擊左邊的+號(hào),選擇New Run Script Phases
下面把這段腳本復(fù)制進(jìn)去(注意:腳本里面PROJECT_PATH_ARR中要設(shè)置自己工程路徑)
參考鏈接:iOS 打包FrameWork腳本 - 狂奔_蝸牛113 - 博客園
#!/bin/sh
#----------------------------------可以自定義的配置項(xiàng)--------------------------------------
#1.需要打包的工程路徑,全部是絕對(duì)路徑
#2.路徑必須到.xcodeproj
#3.如果該工程有多個(gè)Target,需要指定一個(gè)特定的Target來編譯盹沈,在路徑后面加(兩個(gè)下劃線)__Target名稱 例如:xxx/projectName.xcodeproj__TargetName
PROJECT_PATH_ARR=(
"/Users/xxx/Desktop/MyTestSDK/MyTestSDK/MyTestSDK.xcodeproj" \
)
#將PROJECT_PATH_ARR配置的地址【全部】Build出來的SDK所支持架構(gòu)龄章,設(shè)置0或者1
#0:支持真機(jī)和模擬器
#1:只支持真機(jī)
BUILD_SUPPORT_PLATFORM=0
#路徑相關(guān)配置
TMP_PATH="${HOME}/Desktop"? #編譯后的文件存放根路徑,此路徑默認(rèn)是桌面路徑乞封,可以自己指定對(duì)應(yīng)的路徑
#---------------------------------------------------------------------------------------------------------
#開始時(shí)間
start_seconds=$(date +%s);
CURRENT_DATE=`date +%Y-%m-%d_%H-%M-%S`
ROOT_BUILDPATH="${TMP_PATH}/PbLib${CURRENT_DATE}"
TMP_SYMROOT="${ROOT_BUILDPATH}"
TMP_OBJROOT="${TMP_SYMROOT}/TMP_build"
LOG_DIR="${ROOT_BUILDPATH}/Build_Log"
TMP_BUILDSETTING_DIR="${ROOT_BUILDPATH}/TMP_BuildSetting"
#build類型? 有elease和dDebug兩種選項(xiàng)
BUILD_TYPE="Release"
TMP_TARGET_NAME=""
TMP_FULL_PRODUCT_NAME=""
#創(chuàng)建文件路徑
#清除某個(gè)目錄里面的內(nèi)容做裙,如果有則清除內(nèi)容,沒有的直接創(chuàng)建該目錄
#參數(shù)1:目錄
clearDirAll(){
? ? ? ? if[ ! -d $1];
? ? then
? ? ? ? mkdir -p $1
? ? else
? ? ? ? #先刪除肃晚,再創(chuàng)建
? ? ? ? rm -rf $1
? ? ? ? mkdir -p $1
? ? fi
? ? return0
}
#創(chuàng)建Build根目錄
clearDirAll ${ROOT_BUILDPATH}
clearDirAll ${TMP_BUILDSETTING_DIR}
clearDirAll ${LOG_DIR}
#合并真機(jī)和模擬器
#參數(shù)1:當(dāng)前創(chuàng)建的Build目錄
mergeSDK(){
? ? #1.找到真機(jī)和模擬器路徑
? ? tmpIphonesPath="$1/${BUILD_TYPE}-iphoneos"
? ? tmpIphonesimulatorPath="$1/${BUILD_TYPE}-iphonesimulator"
? ? tmpSDKName=""
? ? #2.獲取當(dāng)前SDK名稱
? ? forfilein${tmpIphonesPath}/*
? ? do
? ? ? ? #拿到SDK文件名稱
? ? ? ? tmpName=`basename ${file}`
? ? ? ? if[[ $tmpName =~ $TMP_FULL_PRODUCT_NAME ]];then
? ? ? ? ? ? tmpSDKName=${tmpName}
? ? ? ? fi
? ? done
? ? #3.根據(jù)BUILD_SUPPORT_PLATFORM配置項(xiàng)判斷Build模擬器還是真機(jī)
? ? if[ $BUILD_SUPPORT_PLATFORM -eq0];then? #支持真機(jī)和模擬器
? ? ? ? #判斷當(dāng)前的SDK時(shí).a類型的還是.framework類型的,并且各自合并
? ? ? ? tmpAStr=".a"#當(dāng)前是.a形式的SDK
? ? ? ? tmpFStr=".framework" #當(dāng)前是.framework形式的SDK
? ? ? ? if[[ $tmpSDKName =~ $tmpFStr ]];then
? ? ? ? ? ? #獲取SDK名稱
? ? ? ? ? ? tmpFrameWorkName=${tmpSDKName%.*}
? ? ? ? ? ? #合并SDK
? ? ? ? ? ? #將真機(jī)模式下的FrameWork拷貝一份到根目錄下
? ? ? ? ? ? cp -r ${tmpIphonesPath}/${tmpSDKName} $1/${tmpSDKName}
? ? ? ? ? ? lipo -create"${tmpIphonesPath}/${tmpSDKName}/${tmpFrameWorkName}" "${tmpIphonesimulatorPath}/${tmpSDKName}/${tmpFrameWorkName}" -output "$1/${tmpSDKName}/${tmpFrameWorkName}"
? ? ? ? elif[[ $tmpSDKName =~ $tmpAStr ]];then
? ? ? ? ? ? #合并SDK
? ? ? ? ? ? lipo -create"${tmpIphonesPath}/${tmpSDKName}" "${tmpIphonesimulatorPath}/${tmpSDKName}" -output "$1/${tmpSDKName}"
? ? ? ? fi
? ? elif[ $BUILD_SUPPORT_PLATFORM -eq1];then#只支持真機(jī)
? ? ? ? #如果只支持真機(jī)锚贱,就直接將真機(jī)目錄下的SDK拷貝到根目錄下就可以
? ? ? ? cp -r ${tmpIphonesPath}/${tmpSDKName} $1/${tmpSDKName}
? ? fi
? ? #4.將.h文件拷貝到.a文件的同級(jí)目錄下
? ? find $1-maxdepth1-type d -name"*.h"-exec rm -rf {} \;
? ? find ${tmpIphonesPath} -maxdepth1-type f -name"*.h"-exec mv -f {} $1\;
? ? #5.移除iphones目錄和iphonesimulator目錄
? ? rm -rf"${tmpIphonesPath}"
? ? rm -rf"${tmpIphonesimulatorPath}"
}
#.a庫打包方法,接收兩個(gè)參數(shù)
#參數(shù)1:工程路徑,精確到xxx.xcodeproj
#參數(shù)2:TARGET名稱
buildLibrary(){
? ? if[ -n $1];then
? ? ? ? if[ -n $2];then
? ? ? ? ? ? #創(chuàng)建每個(gè).a的Build路徑
? ? ? ? ? ? buildDir="${ROOT_BUILDPATH}/$2"
? ? ? ? ? ? objRootPath="${TMP_OBJROOT}/$2"
? ? ? ? ? ? echo"--正在編譯 $2........."
? ? ? ? ? ? #創(chuàng)建目錄
? ? ? ? ? ? clearDirAll ${buildDir}
? ? ? ? ? ? logFile="${LOG_DIR}/$2-Build.log"
? ? ? ? ? ? #根據(jù)BUILD_SUPPORT_PLATFORM配置項(xiàng)判斷Build模擬器還是真機(jī)
? ? ? ? ? ? if[ $BUILD_SUPPORT_PLATFORM -eq0];then? #支持真機(jī)和模擬器
? ? ? ? ? ? echo"---------------開始Build模擬器---------------" >>${logFile}
? ? ? ? ? ? #開始Build模擬器
? ? ? ? ? ? xcodebuild? -configuration"${BUILD_TYPE}"ONLY_ACTIVE_ARCH=NO -project"$1"-target"$2"SYMROOT="${TMP_SYMROOT}"OBJROOT="${objRootPath}"BUILD_DIR="${buildDir}"-sdk iphonesimulator clean build >>${logFile}
? ? ? ? ? ? echo"---------------開始Build真機(jī)---------------" >>${logFile}
? ? ? ? ? ? #開始Build真機(jī)
? ? ? ? ? ? xcodebuild -configuration"${BUILD_TYPE}"ONLY_ACTIVE_ARCH=NO -project"$1"-target"$2"SYMROOT="${TMP_SYMROOT}"OBJROOT="${objRootPath}"BUILD_DIR="${buildDir}"-sdk iphoneos clean build >>${logFile}
? ? ? ? ? ? elif[ $BUILD_SUPPORT_PLATFORM -eq1];then#只支持真機(jī)
? ? ? ? ? ? echo"---------------開始Build真機(jī)---------------" >>${logFile}
? ? ? ? ? ? #開始Build真機(jī)
? ? ? ? ? ? xcodebuild -configuration"${BUILD_TYPE}"ONLY_ACTIVE_ARCH=NO -project"$1"-target"$2"SYMROOT="${TMP_SYMROOT}"OBJROOT="${objRootPath}"BUILD_DIR="${buildDir}"-sdk iphoneos clean build >>${logFile}
? ? ? ? ? ? fi
? ? ? ? ? ? #3.合并真機(jī)和模擬器
? ? ? ? ? ? mergeSDK ${buildDir};
? ? ? ? ? ? #4.移除工程根目錄下的build目錄
? ? ? ? ? ? tmpPath=$1
? ? ? ? ? ? projectPath=${tmpPath%/*}
? ? ? ? ? ? rm -rf"${projectPath}/build"
? ? ? ? ? ? rm -rf"${TMP_OBJROOT}"
? ? ? ? else
? ? ? ? ? ? echo"Target不能為空"
? ? ? ? fi
? ? else
? ? ? ? echo"工程路徑不能為空"
? ? fi
}
#導(dǎo)出BuildSetting文件并且找出TARGET_NAME和PRODUCT_NAME環(huán)境變量的值
#param1:工程路徑
#param2:TARGET名稱关串,如果沒有可以傳nil
readBuildSetting(){
? ? #0.清除全局變量的值
? ? TMP_TARGET_NAME=""
? ? TMP_FULL_PRODUCT_NAME=""
? ? #1.將工程工程對(duì)應(yīng)Target的BuildSetting文件導(dǎo)出到本地
? ? BuildSettingFile="${TMP_BUILDSETTING_DIR}/tmp_buildSetting.txt"
? ? if[ -n"$1"];then
? ? ? ? cmdStr="xcodebuild -list -project $1 -showBuildSettings >${BuildSettingFile}"
? ? ? ? if[ -n"$2"];then
? ? ? ? ? ? cmdStr="xcodebuild -list -project $1 -target $2 -showBuildSettings >${BuildSettingFile} "
? ? ? ? fi
? ? ? ? #執(zhí)行導(dǎo)出BuildSetting的文件
#? ? ? ? echo "命令:${cmdStr}"
? ? ? ? eval ${cmdStr}
? ? fi
? ? #2.解析導(dǎo)出的BuildSetting文件拧廊,找出其中的TARGET_NAME和PRODUCT_NAME,并賦值給TMP_TARGET_NAME,TMP_PRODUCT_NAME
? ? IFS='='
? ? whilereadk v
? ? do
? ? if[["$k"== *FULL_PRODUCT_NAME* ]];then
?? ? ? TMP_FULL_PRODUCT_NAME=$(echo $v | sed's/[[:space:]]//g')
? ? elif[["$k"== *TARGET_NAME* ]];then
?? ? ? TMP_TARGET_NAME=$(echo $v | sed's/[[:space:]]//g')
? ? fi
? ? done< ${BuildSettingFile}
#? ? echo "TMP_FULL_PRODUCT_NAME=${TMP_FULL_PRODUCT_NAME}? TMP_TARGET_NAME=${TMP_TARGET_NAME}"
? ? rm -rf"${BuildSettingFile}"
}
startBuild(){
? ? #1.遍歷數(shù)組悍缠,根據(jù)路徑截取到相應(yīng)的工程路徑以及工程名
? ? forproPathin${PROJECT_PATH_ARR[*]}
? ? do
? ? ? ? #2.獲取工程路徑
? ? ? ? projectPath=${proPath}
? ? ? ? targetName=""
? ? ? ? #3.判斷工程路徑中是否包含__,如果包含了則說明指定了Target
? ? ? ? tmpStr="__"
? ? ? ? if[[ $proPath =~ $tmpStr ]]
? ? ? ? then
? ? ? ? ? ? projectPath=${proPath%__*}
? ? ? ? ? ? #取到需要的Target名稱
? ? ? ? ? ? targetName=${proPath#*__}
? ? ? ? fi
? ? ? ? #4.判斷targetName是否為空卦绣,如果為空則代表TargetName和工程名稱相同
#? ? ? ? if [ -z "${targetName}" ];then
#? ? ? ? ? ? xcodeproj=${projectPath##*/}
#? ? ? ? ? ? projectName=${xcodeproj%.*}
#? ? ? ? ? ? targetName=${projectName}
#? ? ? ? fi
? ? ? ? #5.讀取TARGET_NAME和PRODUCT_NAME
? ? ? ? readBuildSetting ${projectPath} ${targetName}
? ? ? ? #6.調(diào)用Build函數(shù)進(jìn)行Build
? ? ? ? buildLibrary ${projectPath} ${TMP_TARGET_NAME}
? ? done
}
echo "-----------------開始Build-----------------"
startBuild;
end_seconds=$(date +%s);
echo "-----------------Build完成? 耗時(shí):$((end_seconds-start_seconds))s-----------------"
#移除BuildSetting工作目錄
rm -rf "${TMP_BUILDSETTING_DIR}"
open ${ROOT_BUILDPATH}
如圖所示:
最后編譯,command + B飞蚓,編譯通過在桌面(不一定在桌面滤港,需要看腳本中自己設(shè)置的路徑)中找到framework,拷貝出來
2趴拧、Demo與SDK的關(guān)聯(lián)
把打包好的framework拖到demo里面
使用SDK溅漾,運(yùn)行demo
運(yùn)行的結(jié)果
這時(shí)候SDK跟Demo就關(guān)聯(lián)起來了,此時(shí)修改下面SDK中的代碼著榴,運(yùn)行demo就是修改后的效果添履,然后就可以愉快的在這個(gè)工程里面開發(fā)調(diào)試SDK了,如果我把MyView的顏色設(shè)置為yellow脑又,再去運(yùn)行demo暮胧,看一下效果
最后的最后,把這個(gè)工程上傳到SVN就可以愉快的開發(fā)了问麸。往衷。。以上是我個(gè)人的理解严卖,如有錯(cuò)誤席舍,請各位大牛批評(píng)指正,文中framework的打包方法參考網(wǎng)上資料哮笆,參考鏈接:qingmang.me/articles/5162103427194116731/