由于公司需要焕阿,需有一套代碼出多個(gè)APP钾挟,(有企業(yè)版也有Store版),同時(shí)企業(yè)版又分多個(gè)渠道(二維碼放在不同的地方推廣)莺琳,由于企業(yè)版和Store版證書(shū)App的Logo还棱、啟動(dòng)圖、友盟惭等、支付珍手、分享scheme什么的都不相同,一套代碼出好幾個(gè)app辞做,外加幾個(gè)渠道琳要,一次打近十個(gè)包,改到很來(lái)多時(shí)候自己都蒙了秤茅,所以為了不出錯(cuò)稚补,也是為了不頭疼所以就只能想想解決辦法。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 一個(gè)自動(dòng)打包腳本是多么的重要.pic.jpg
1.多target
2.buildSetting中設(shè)置不同的宏框喳,以區(qū)分是哪個(gè)target
3.將channel字?jǐn)嗉尤氲絧list中课幕,以區(qū)分多版本
4.PlistBuddy修改plist(version及channel)
5.打包腳本
一厦坛、多target
如果只是一套代碼多個(gè)APP可以創(chuàng)建多個(gè)target,每個(gè)target一套配置文件
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?添加target.jpg
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 三處修改.jpg
1.點(diǎn)擊工程
2.右鍵target點(diǎn)擊Duplicate
3.修改target名稱(chēng)乍惊、修改plist名稱(chēng)杜秸、修改scheme(點(diǎn)擊上圖3處選擇EditScheme->MamagerScheme,修改一下名稱(chēng))
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 修改Scheme.jpg
4.添加宏代碼中通過(guò)判斷是否定義了該宏來(lái)判斷當(dāng)前是哪個(gè)target
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?添加宏.jpg
5.如果你是swift和oc混編的工程interfaceHeader原來(lái)是一個(gè)配置的值润绎,由于改了target名稱(chēng)回導(dǎo)致新建的target找不到這個(gè)文件撬碟,所以要這個(gè)配置值改為固定值
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?修改interfaceHeader.jpg
6.代碼中判斷當(dāng)前是哪個(gè)target
#ifdef HSENTERPRISE
?//hs
#elif defined XUETUENTERPRISE
//xuetu
#endif
二、多渠道
多渠道主要是給每個(gè)app加一個(gè)標(biāo)識(shí)符莉撇,以區(qū)分是哪個(gè)渠道呢蛤,我們是在每次網(wǎng)絡(luò)請(qǐng)求時(shí)都會(huì)上傳當(dāng)前channel,用以統(tǒng)計(jì)每個(gè)渠道的注冊(cè)量或者購(gòu)買(mǎi)等,這里channel字段要加在plist當(dāng)中棍郎,通過(guò)自動(dòng)腳本打包顾稀,每次修改一下channel字段,生成對(duì)應(yīng)的ipa包坝撑。不然手動(dòng)改真的爆炸。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 將channel字段加入到plist中.jpg
每個(gè)target都有對(duì)應(yīng)的一個(gè)info-plist粮揉,所以我們可以通過(guò)以下方法獲取到當(dāng)前target綁定的plist巡李,從而獲取channel,當(dāng)然上面通過(guò)宏來(lái)判斷是哪個(gè)target扶认,也可以在plist文件加一個(gè)標(biāo)識(shí)符來(lái)區(qū)分是哪個(gè)target侨拦。
NSDictionary*infoDictionary=[[NSBundle mainBundle]infoDictionary];NSString*channel=[infoDictionary objectForKey:@"channel"];
三、PlistBuddy修改plist
PlistBuddy是mac自帶的命令行修改plist的工具辐宾,同樣我們也可以在腳本中通過(guò)PlistBuddy來(lái)修改plist
終端輸入/usr/libexec/PlistBuddy --help可以查看幫助文檔
舉幾個(gè)常用的例子:
添加
/usr/libexec/PlistBuddy -c "Add :addtest string xixi " /Users/hsedu/Desktop/hskaoyanStrore-Info.plist
修改
/usr/libexec/PlistBuddy -c "Set :addtest haha " /Users/hsedu/Desktop/hskaoyanStrore-Info.plist
輸出
/usr/libexec/PlistBuddy -c "print addtest" /Users/hsedu/Desktop/hskaoyanStrore-Info.plist
刪除
/usr/libexec/PlistBuddy -c "Delete :addtest " /Users/hsedu/Desktop/hskaoyanStrore-Info.plist
添加字典
/usr/libexec/PlistBuddy -c "add :adddict:name string zhangsan " /Users/hsedu/Desktop/hskaoyanStrore-Info.plist
創(chuàng)建數(shù)組
/usr/libexec/PlistBuddy -c "add :arrayname array " /Users/hsedu/Desktop/hskaoyanStrore-Info.plist
為數(shù)組增加值
/usr/libexec/PlistBuddy -c "add :arrayname:0 string lisi " /Users/hsedu/Desktop/hskaoyanStrore-Info.plist
四狱从、自動(dòng)打包腳本
1、shell幾個(gè)常用語(yǔ)句
定義變量
APPVERSION="2.1.7"
For in循環(huán)(變量無(wú)需聲明直接用)
archiveIpas="? vkeEnterprise xuetuEnterprise vkeStore hsStore";for produce in $archiveIpasdo#codingdone
函數(shù)及case($1代表傳入的參數(shù))
teamID=$(getteamID ${produce})function getteamID(){? ? teamid=""? ? case $1 in? ? hsEnterprise)? ? teamid="93C8xxxxx";? ? ;;? ? hsStore)? ? teamid="5Txxxxxxx";? ? ;;? ? vkeEnterprise)? ? teamid="93CxxxX";? ? ;;? ? vkeStore)? ? teamid="xxxxxJ28";? ? ;;? ? xuetuEnterprise)? ? teamid="9xxxxxYX";? ? ;;? ? esac? ? echo $teamid;}
if語(yǔ)句
methodString=""B="Enterprise"#判斷是否包含Enterprise叠纹,從而判定是企業(yè)版還是stroe版證書(shū)if [[ $produce == *$B* ]]thenmethodString="enterprise"#包含elsemethodString="ad-hoc"#不包含fi
2.xcodebuild 打包
需要哪些準(zhǔn)備
teamID
可以在appleDevelop賬號(hào)的Membership Details中查看開(kāi)發(fā)賬號(hào)的teamID
可以在project文件顯示包內(nèi)容中的project.pbxproj 中搜索team查看teamID
證書(shū)名字
可以在鑰匙串顯示簡(jiǎn)介中查看
描述文件(Provisioning Profiles)UUID
可以終端中vi 描述文件(Provisioning Profiles)查看UUID
3.生成xcarchive文件
xcodebuild -help可查看xcodebuild相關(guān)幫助文檔
man xcodebuild可查看xcodebuild相關(guān)幫助文檔
xcodebuild -list可查看當(dāng)前工程target季研、Configurations以及scheme
#archive workspace-用cocoaPods的#xcodebuild-archivePath"${archiveProducePath}${produce}${channel}.xcarchive"-workspace hskaoyan.xcworkspace-scheme"${produce}"-sdk iphoneos-configuration ${configuration}CODE_SIGN_IDENTITY="$IDENTITY"PROVISIONING_PROFILE="$PROFILE_UUID"archive#archive project-沒(méi)用cocoaPods或者cocoaPods在工程內(nèi),不含workspacexcodebuild-archivePath"${archiveProducePath}${produce}${channel}.xcarchive"-project hskaoyan.xcodeproj-scheme"${produce}"-sdk iphoneos-configuration ${configuration}CODE_SIGN_IDENTITY="$IDENTITY"PROVISIONING_PROFILE="$PROFILE_UUID"archive
-archivePath生成archive文件的存放路徑
-workspaceworkspace 名稱(chēng)
-sdk所用sdk(xcodebuild -showsdks可查看可用sdk)
iOSSDKs:iOS 10.2? ? ? ? ? ? ? ? ? ? ? ? -sdk iphoneos10.2iOS SimulatorSDKs:Simulator - iOS 10.2? ? ? ? ? ? -sdk iphonesimulator10.2macOSSDKs:macOS 10.12? ? ? ? ? ? ? ? ? ? -sdk macosx10.12tvOSSDKs:tvOS 10.1? ? ? ? ? ? ? ? ? ? ? -sdk appletvos10.1tvOS SimulatorSDKs:Simulator - tvOS 10.1? ? ? ? ? -sdk appletvsimulator10.1watchOSSDKs:watchOS 3.1? ? ? ? ? ? ? ? ? ? -sdk watchos3.1watchOS SimulatorSDKs:Simulator - watchOS 3.1? ? ? ? -sdk watchsimulator3.1
-configuration選擇configuration
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 配置configuration.png
CODE_SIGN_IDENTITY證書(shū)名稱(chēng)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 證書(shū)名稱(chēng).png
PROVISIONING_PROFILE描述文件UUID
進(jìn)入描述文件查看UUID.png
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? UUID.png
4.導(dǎo)出ipa包
#導(dǎo)出ipaxcodebuild -exportArchive -archivePath "${archiveProducePath}${produce}${channel}.xcarchive"? -exportPath "${ipaProducePath}${produce}${channel}"? -exportOptionsPlist "$optionsPlist_FILE_PATH"
-archivePath剛才生成的archive文件路徑
-exportPathipa包導(dǎo)出路徑
-exportOptionsPlist導(dǎo)出相關(guān)配置的plist
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? exportOptionsPlist.png
可以通過(guò)修改method參數(shù)來(lái)選擇你要的包是adhoc還是企業(yè)版或者是store(不通包所需的描述文件不同)
5.自動(dòng)打包腳本最終版
#!/bin/bashecho "? ? ? _? ? ? ? ? ------ _? ? ? ? ? ? ? ? ? "echo "? ? (_)? ? ? ? / /? ? ) )? ? ? ___? ? ? ? "echo "? ? / /? ? ? ? / /? ? ) )? ? ? / __ \? ? ? "echo "? / /? ? ? ? / /__ _)_)? ? ? / /_/ /\? ? ? "echo "? /_/? ? ? ? /_/? ? ? ? ? ? ? \____/\ \? ? "#hsEnterprise xx企業(yè)版#hsStore? ? ? xxStore版#vkeEnterprise? Vx企業(yè)版#vkeStore? ? ? ? xxStore版#xuetuEnterprise? ? x途企業(yè)版#*****************************************設(shè)置區(qū)域**********************************************##設(shè)置archive生成的.xcarchive文件路徑(絕對(duì)路徑)archiveProducePath="/Users/hsedu/Desktop/ipa/"#設(shè)置ipa包生成路徑(絕對(duì)路徑)ipaProducePath="/Users/hsedu/Desktop/ipa/"#設(shè)置Plist文件路徑前半部分部分(后半部分需要?jiǎng)討B(tài)拼接)infoPlist_HEAD_PATH=$(pwd)#設(shè)置exportOptions.plist文件路徑optionsPlist_FILE_PATH="$(pwd)/exportOptions.plist"#APP版本號(hào)APPVERSION="2.1.7"#設(shè)置是打測(cè)試版還是發(fā)布版本(Release or Debug)configuration="Release"#設(shè)置為哪些App打包ipa hsEnterprise vkeEnterprise xuetuEnterprise vkeStore hsStorearchiveIpas=" vkeStore vkeEnterprise xuetuEnterprise vkeStore hsStore";#設(shè)置APP所對(duì)應(yīng)的渠道標(biāo)志function getChannel(){? ? channel=""? ? case $1 in? ? hsEnterprise)? ? channel="www xxbang xixxwu xxshi";? ? ;;? ? hsStore)? ? channel="www xx";? ? ;;? ? vkeEnterprise)? ? channel="xxx xx";? ? ;;? ? vkeStore)? ? channel="xxx xx";? ? ;;? ? xuetuEnterprise)? ? channel="www xx";? ? ;;? ? esac? ? echo $channel;}#設(shè)置APP所對(duì)應(yīng)的teamID的名字function getteamID(){? ? teamid=""? ? case $1 in? ? hsEnterprise)? ? teamid="93xxxxxYX";? ? ;;? ? hsStore)? ? teamid="5xxxxAH36";? ? ;;? ? vkeEnterprise)? ? teamid="93xxxxxX";? ? ;;? ? vkeStore)? ? teamid="xxxxx28";? ? ;;? ? xuetuEnterprise)? ? teamid="9xxxxZYX";? ? ;;? ? esac? ? echo $teamid;}#設(shè)置APP所對(duì)應(yīng)的CODE_SIGN_IDENTITY的名字function getCODE_SIGN_IDENTITY(){? ? identity=""? ? case $1 in? ? hsEnterprise)? ? identity="iPhone Distribution: xxx Network Technology Beijing Co.Ltd.";? ? ;;? ? hsStore)? ? identity="iPhone Distribution: xxxao (5x8xxx6)";? ? ;;? ? vkeEnterprise)? ? identity="iPhone Distribution: xxx Network Technology Beijing Co.Ltd.";? ? ;;? ? vkeStore)? ? identity="iPhone Distribution: xxxx Network Technology (Beijing) Co.,Ltd. (Sxxxx8)";? ? ;;? ? xuetuEnterprise)? ? identity="iPhone Distribution: xxxr Network Technology Beijing Co.Ltd.";? ? ;;? ? esac? ? echo $identity;}#設(shè)置APP所對(duì)應(yīng)的PROFILE_UUID的名字function getPROFILE_UUID(){? ? identity=""? ? case $1 in? ? hsEnterprise)? ? identity="7xxxxxx3-196exxcxx6";? ? ;;? ? hsStore)#0exxd79-db21-4xxxcxxx8-118xxxxx5d6 adhoc#36xx17xx-17xx-4xxx-b4xxx25xxxx66c appstore? ? identity="0eb8xxx9-db21-4bxc-8exx-118xxxxxd6";? ? ;;? ? vkeEnterprise)? ? identity="bdxxx6xx-9b92-4xx4-xxx8-cdxxxdb3";? ? ;;? ? vkeStore)#183fxxxxxxxxx07 adhoc#1535ba7dxxxxxxd98 appstore? ? identity="1xxfxxx-2d2f-4xxc-8bxxx8-527fxx44b07";? ? ;;? ? xuetuEnterprise)? ? identity="bccxxx9-cxxx-4xxx-xx0-2e8xxxx5";? ? ;;? ? esac? ? echo $identity;}#*****************************************Coding**********************************************#pwd | grep -q '[[:blank:]]' && {echo "Source path: $(pwd)"echo "Out of tree builds are impossible with whitespace in source path."exit 1;}for produce in $archiveIpasdoecho "${produce}"#*****************************************修改infoPlistVersion**********************************************##拼接info.plist路徑infoPlist_FILE_PATH="${infoPlist_HEAD_PATH}/${produce}-info.plist"echo "infoPlistPath:${infoPlist_FILE_PATH}"#修改plist中Version/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $APPVERSION" $infoPlist_FILE_PATH#輸出修改后versionversionPrint=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" $infoPlist_FILE_PATH)echo "plistVersion:$versionPrint"#****************************************修改exportOptionPlist***************************************##method : String#Describes how Xcode should export the archive. Available options: app-store, package, ad-hoc, enterprise, development, and developer-id. The list of options varies based on the type of archive. Defaults to development.methodString=""B="Enterprise"#判斷是否包含Enterprise誉察,從而判定是企業(yè)版還是stroe版證書(shū)if [[ $produce == *$B* ]]thenmethodString="enterprise"#包含elsemethodString="ad-hoc"#不包含fi#修改plist中method/usr/libexec/PlistBuddy -c "Set :method $methodString" $optionsPlist_FILE_PATH#輸出修改后methodmethodPrint=$(/usr/libexec/PlistBuddy -c "Print method" $optionsPlist_FILE_PATH)echo "plistMethod:$methodPrint"#設(shè)置provisioningProfileNameteamID=$(getteamID ${produce})echo "${teamID}"#修改plist中teamID/usr/libexec/PlistBuddy -c "Set :teamID $teamID" $optionsPlist_FILE_PATH#輸出修改后teamIDchannelPrint=$(/usr/libexec/PlistBuddy -c "Print teamID" $optionsPlist_FILE_PATH)echo "plistTeamID:$channelPrint"for channel in $(getChannel ${produce})do#修改plist中channel/usr/libexec/PlistBuddy -c "Set :channel $channel" $infoPlist_FILE_PATH#輸出修改后channelchannelPrint=$(/usr/libexec/PlistBuddy -c "Print channel" $infoPlist_FILE_PATH)echo "plistChannel:$channelPrint"PROFILE_UUID=$(getPROFILE_UUID ${produce})IDENTITY=$(getCODE_SIGN_IDENTITY ${produce})#archive workspace-用cocoaPods的#xcodebuild -archivePath "${archiveProducePath}${produce}${channel}.xcarchive" -workspace hskaoyan.xcworkspace? -scheme "${produce}"? -sdk iphoneos -configuration ${configuration}? archive#archive project-沒(méi)用cocoaPods或者cocoaPods在工程內(nèi)与涡,不含workspacexcodebuild -archivePath "${archiveProducePath}${produce}${channel}.xcarchive" -project hskaoyan.xcodeproj? -scheme "${produce}"? -sdk iphoneos -configuration ${configuration} CODE_SIGN_IDENTITY="$IDENTITY" PROVISIONING_PROFILE="$PROFILE_UUID" archive#rvm list 可查看安裝的ruby列表#rvm system#導(dǎo)出ipaxcodebuild -exportArchive -archivePath "${archiveProducePath}${produce}${channel}.xcarchive"? -exportPath "${ipaProducePath}${produce}${channel}"? -exportOptionsPlist "$optionsPlist_FILE_PATH"donedoneprintf "\n(-_-)-Complete-(-_-)\n\n"exit 0
注意
現(xiàn)在xcode都是自動(dòng)簽名的,因?yàn)槟_本需要指定證書(shū)和描述文件所以工程中不能使用自動(dòng)簽名持偏,當(dāng)然也可以不指定驼卖,采用自動(dòng)簽名,但是具體打出包是什么類(lèi)型不知道鸿秆,沒(méi)去研究酌畜。下面兩個(gè)是遇到的錯(cuò)誤及解決的辦法
Error Domain=IDEDistributionErrorDomain Code=14 "No applicable devices found." UserInfo={NSLocalizedDescription=No applicable devices found.}
這里
遇到的坑:①? Code=1 (這個(gè)操作不能完成)、② Code=14 (沒(méi)有試用的設(shè)備 Domain=IDEDistributionErrorDomain Code=14 "No applicable devices found.)卿叽、③ "rvm use ..." rvm不可用的問(wèn)題桥胞。
解決辦法:code=1恳守,證書(shū)有問(wèn)題,重做證書(shū)埠戳。code=14井誉,先rvm system,然后再export也可以整胃。如果rvm不能用颗圣,出現(xiàn)rvm use ...、rvm找不到等問(wèn)題屁使,那就是使用的rvm或者rvm路徑不正確在岂,導(dǎo)致使用的默認(rèn)ruby有問(wèn)題,這里需要使用系統(tǒng)的ruby蛮寂,需要查看本機(jī)rvm蔽午。個(gè)人遇到的問(wèn)題是,本機(jī)rvm路徑有問(wèn)題酬蹋,PATH里面的rvm路徑也有問(wèn)題及老,找不到正確的rvm以及ruby。unset rvm 清空PATH范抓,重新添加相關(guān)路徑(source /ect/paths)即可骄恶,刪除rvm(不需要rvm,rvm system不能用就刪除rvm不需要)匕垫,重啟僧鲁。
如果工程中某個(gè)target報(bào)某個(gè)類(lèi)沒(méi)有找到,那一定是創(chuàng)建類(lèi)的時(shí)候忘記勾選targt了象泵,(我這是git兩個(gè)分支合并的時(shí)候運(yùn)行報(bào)的xxx這個(gè)類(lèi)找不到)
點(diǎn)擊這個(gè)類(lèi)寞秃,右邊類(lèi)的屬性中target memberShip勾選一下即可
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?勾選一下即可.pic.jpg