由于公司需要,需有一套代碼出多個APP霉涨,(有企業(yè)版也有Store版)钥勋,同時企業(yè)版又分多個渠道(二維碼放在不同的地方推廣),由于企業(yè)版和Store版證書App的Logo科阎、啟動圖述吸、友盟、支付萧恕、分享scheme什么的都不相同刚梭,一套代碼出好幾個app肠阱,外加幾個渠道票唆,一次打近十個包,改到很來多時候自己都蒙了屹徘,所以為了不出錯走趋,也是為了不頭疼所以就只能想想解決辦法。
1.多target
2.buildSetting中設置不同的宏噪伊,以區(qū)分是哪個target
3.將channel字斷加入到plist中簿煌,以區(qū)分多版本
4.PlistBuddy修改plist(version及channel)
5.打包腳本
一、多target
如果只是一套代碼多個APP可以創(chuàng)建多個target鉴吹,每個target一套配置文件
1.點擊工程
2.右鍵target點擊Duplicate
3.修改target名稱姨伟、修改plist名稱、修改scheme(點擊上圖3處選擇EditScheme->MamagerScheme豆励,修改一下名稱)
4.添加宏代碼中通過判斷是否定義了該宏來判斷當前是哪個target
5.如果你是swift和oc混編的工程interfaceHeader原來是一個配置的值夺荒,由于改了target名稱回導致新建的target找不到這個文件,所以要這個配置值改為固定值
6.代碼中判斷當前是哪個target
#ifdef HSENTERPRISE
//hs
#elif defined XUETUENTERPRISE
//xuetu
#endif
二良蒸、多渠道
多渠道主要是給每個app加一個標識符技扼,以區(qū)分是哪個渠道,我們是在每次網(wǎng)絡請求時都會上傳當前channel,用以統(tǒng)計每個渠道的注冊量或者購買等嫩痰,這里channel字段要加在plist當中剿吻,通過自動腳本打包,每次修改一下channel字段串纺,生成對應的ipa包丽旅。不然手動改真的爆炸椰棘。
每個target都有對應的一個info-plist,所以我們可以通過以下方法獲取到當前target綁定的plist魔招,從而獲取channel晰搀,當然上面通過宏來判斷是哪個target,也可以在plist文件加一個標識符來區(qū)分是哪個target办斑。
NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
NSString * channel = [infoDictionary objectForKey:@"channel"];
三外恕、PlistBuddy修改plist
PlistBuddy是mac自帶的命令行修改plist的工具,同樣我們也可以在腳本中通過PlistBuddy來修改plist
終端輸入/usr/libexec/PlistBuddy --help
可以查看幫助文檔
舉幾個常用的例子:
添加
/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
四乡翅、自動打包腳本
1鳞疲、shell幾個常用語句
- 定義變量
APPVERSION="2.1.7"
- For in循環(huán)(變量無需聲明直接用)
archiveIpas=" vkeEnterprise xuetuEnterprise vkeStore hsStore";
for produce in $archiveIpas
do
#coding
done
- 函數(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語句
methodString=""
B="Enterprise"
#判斷是否包含Enterprise,從而判定是企業(yè)版還是stroe版證書
if [[ $produce == *$B* ]]
then
methodString="enterprise"
#包含
else
methodString="ad-hoc"
#不包含
fi
2.xcodebuild 打包
需要哪些準備
- teamID
- 可以在appleDevelop賬號的Membership Details中查看開發(fā)賬號的teamID
- 可以在project文件顯示包內(nèi)容中的project.pbxproj 中搜索team查看teamID
- 證書名字
- 可以在鑰匙串顯示簡介中查看
- 描述文件(Provisioning Profiles)UUID
- 可以終端中vi 描述文件(Provisioning Profiles)查看UUID
3.生成xcarchive文件
xcodebuild -help
可查看xcodebuild相關幫助文檔
man xcodebuild
可查看xcodebuild相關幫助文檔
xcodebuild -list
可查看當前工程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-沒用cocoaPods或者cocoaPods在工程內(nèi)尚洽,不含workspace
xcodebuild -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文件的存放路徑
-workspace
workspace 名稱
-sdk
所用sdk(xcodebuild -showsdks
可查看可用sdk)
iOS SDKs:
iOS 10.2 -sdk iphoneos10.2
iOS Simulator SDKs:
Simulator - iOS 10.2 -sdk iphonesimulator10.2
macOS SDKs:
macOS 10.12 -sdk macosx10.12
tvOS SDKs:
tvOS 10.1 -sdk appletvos10.1
tvOS Simulator SDKs:
Simulator - tvOS 10.1 -sdk appletvsimulator10.1
watchOS SDKs:
watchOS 3.1 -sdk watchos3.1
watchOS Simulator SDKs:
Simulator - watchOS 3.1 -sdk watchsimulator3.1
-configuration
選擇configuration
CODE_SIGN_IDENTITY
證書名稱PROVISIONING_PROFILE
描述文件UUID
4.導出ipa包
#導出ipa
xcodebuild -exportArchive -archivePath "${archiveProducePath}${produce}${channel}.xcarchive" -exportPath "${ipaProducePath}${produce}${channel}" -exportOptionsPlist "$optionsPlist_FILE_PATH"
-archivePath
剛才生成的archive文件路徑
-exportPath
ipa包導出路徑
-exportOptionsPlist
導出相關配置的plist
可以通過修改method參數(shù)來選擇你要的包是adhoc還是企業(yè)版或者是store(不通包所需的描述文件不同)
5.自動打包腳本最終版
#!/bin/bash
echo " _ ------ _ "
echo " (_) / / ) ) ___ "
echo " / / / / ) ) / __ \ "
echo " / / / /__ _)_) / /_/ /\ "
echo " /_/ /_/ \____/\ \ "
#hsEnterprise xx企業(yè)版
#hsStore xxStore版
#vkeEnterprise Vx企業(yè)版
#vkeStore xxStore版
#xuetuEnterprise x途企業(yè)版
#*****************************************設置區(qū)域**********************************************#
#設置archive生成的.xcarchive文件路徑(絕對路徑)
archiveProducePath="/Users/hsedu/Desktop/ipa/"
#設置ipa包生成路徑(絕對路徑)
ipaProducePath="/Users/hsedu/Desktop/ipa/"
#設置Plist文件路徑前半部分部分(后半部分需要動態(tài)拼接)
infoPlist_HEAD_PATH=$(pwd)
#設置exportOptions.plist文件路徑
optionsPlist_FILE_PATH="$(pwd)/exportOptions.plist"
#APP版本號
APPVERSION="2.1.7"
#設置是打測試版還是發(fā)布版本(Release or Debug)
configuration="Release"
#設置為哪些App打包ipa hsEnterprise vkeEnterprise xuetuEnterprise vkeStore hsStore
archiveIpas=" vkeStore vkeEnterprise xuetuEnterprise vkeStore hsStore";
#設置APP所對應的渠道標志
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;
}
#設置APP所對應的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;
}
#設置APP所對應的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;
}
#設置APP所對應的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 $archiveIpas
do
echo "${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
#輸出修改后version
versionPrint=$(/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版證書
if [[ $produce == *$B* ]]
then
methodString="enterprise"
#包含
else
methodString="ad-hoc"
#不包含
fi
#修改plist中method
/usr/libexec/PlistBuddy -c "Set :method $methodString" $optionsPlist_FILE_PATH
#輸出修改后method
methodPrint=$(/usr/libexec/PlistBuddy -c "Print method" $optionsPlist_FILE_PATH)
echo "plistMethod:$methodPrint"
#設置provisioningProfileName
teamID=$(getteamID ${produce})
echo "${teamID}"
#修改plist中teamID
/usr/libexec/PlistBuddy -c "Set :teamID $teamID" $optionsPlist_FILE_PATH
#輸出修改后teamID
channelPrint=$(/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
#輸出修改后channel
channelPrint=$(/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-沒用cocoaPods或者cocoaPods在工程內(nèi)靶累,不含workspace
xcodebuild -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
#導出ipa
xcodebuild -exportArchive -archivePath "${archiveProducePath}${produce}${channel}.xcarchive" -exportPath "${ipaProducePath}${produce}${channel}" -exportOptionsPlist "$optionsPlist_FILE_PATH"
done
done
printf "\n(-_-)-Complete-(-_-)\n\n"
exit 0
注意
現(xiàn)在xcode都是自動簽名的腺毫,因為腳本需要指定證書和描述文件所以工程中不能使用自動簽名,當然也可以不指定挣柬,采用自動簽名潮酒,但是具體打出包是什么類型不知道,沒去研究邪蛔。下面兩個是遇到的錯誤及解決的辦法
Error Domain=IDEDistributionErrorDomain Code=14 "No applicable devices found." UserInfo={NSLocalizedDescription=No applicable devices found.}
這里
遇到的坑:① Code=1 (這個操作不能完成)急黎、② Code=14 (沒有試用的設備 Domain=IDEDistributionErrorDomain Code=14 "No applicable devices found.)、③ "rvm use ..." rvm不可用的問題侧到。
解決辦法:code=1勃教,證書有問題,重做證書匠抗。code=14故源,先rvm system,然后再export也可以汞贸。如果rvm不能用绳军,出現(xiàn)rvm use ...、rvm找不到等問題著蛙,那就是使用的rvm或者rvm路徑不正確删铃,導致使用的默認ruby有問題,這里需要使用系統(tǒng)的ruby踏堡,需要查看本機rvm猎唁。個人遇到的問題是,本機rvm路徑有問題,PATH里面的rvm路徑也有問題诫隅,找不到正確的rvm以及ruby腐魂。unset rvm 清空PATH,重新添加相關路徑(source /ect/paths)即可逐纬,刪除rvm(不需要rvm蛔屹,rvm system不能用就刪除rvm不需要),重啟豁生。
如果工程中某個target報某個類沒有找到兔毒,那一定是創(chuàng)建類的時候忘記勾選targt了,(我這是git兩個分支合并的時候運行報的xxx這個類找不到)
點擊這個類甸箱,右邊類的屬性中target memberShip勾選一下即可