項目每次更新要打十幾個包,廣發說傳承下來的自動打包腳本忽然很差使了,如今每次打包上傳都要弄到凌晨,之後更名叫稀發好了。看着他愈來愈禿的頭,我這父愛就藏匿不住,必需要幫他分擔(固然是被逼的)。json
這個項目十幾個包,不一樣圖標、App名字,手動打包不但慢,並且重複枯燥的工做出錯機率也指數上升。因此若是你的項目也要打幾個包的話,花時間學習自動打包仍是值得的。若是隻用打一個包,雖然自動打包時間會快點,但學習成本仍是在那,見仁見智了。api
重點是,利用重簽名修改自定義的圖片、App名字等,不用重複編譯,能極大縮短打包時間。數組
網上關於證書配置不乏好文章,一搜一大堆,但大多都沒有介紹分別有什麼用。xcode
包含電腦的信息。因此建立時不須要填任何和發佈等有關的信息。bash
電腦擁有這個證書後,有權對該Apple Developer的ID下全部App進行真機測試、打包、發佈。注意這裏,並未指定App,換句話說,和App無關。併發
包含電腦的信息和Apple Developer的信息。app
上面提到了Certificates包含了電腦的信息,這個信息來自於CSR。因此在建立Certificates時,須要提交CSR。curl
上面提到,擁有此證書纔有權作那些事。若是另外一部電腦想發佈,也須要證書。若是又建立一個新證書也能解決,但通常一個開發者賬號建立一個發佈證書就夠了,並且蘋果對這證書數量有限制。這時候導出p12文件,至關於拷貝了一份證書(不佔蘋果限制數量)。給另外一部電腦安裝後,另外一部電腦就有權了。iphone
到這裏,筆者就迷惑了CSR包含了電腦的信息,而後又能拷貝給其餘電腦用,有什麼用呢。但願大佬能解惑。ide
上面提到的與App無直接關係,如下才與App創建起聯繫。
在該Apple Developer下注冊App。這裏要填Name和Bundle ID。這裏的Bundle ID將在Xcode中匹配證書。
以前聽李大神說,新建一個新項目,而後改成公司項目中的Bundle ID,App也能真機測試,就是由於經過Bundle ID來匹配。
包含appID,開發者證書。
建立時,開發版和發佈版有區別。前者要選設備,後者不用。
建立下載後,Xcode就會自動匹配,固然也能夠手動匹配。
本文采用的是xcodebuild。
提及自動打包就腦袋疼。一直對命令行有恐懼,只能一步一步來了。先了解命令行命令,而後新建一個項目熟悉一下。
xcodebuild
是xcode提供的打包項目或者工程的命令。
輸入man xcodebuild
能夠查看文檔。
這裏引用大佬的總結。
輸入xcodebuild -h
能夠查看幫助。
Usage: xcodebuild [-project <projectname>] [[-target <targetname>]...|-alltargets] [-configuration <configurationname>] [-arch <architecture>]... [-sdk [<sdkname>|<sdkpath>]] [-showBuildSettings] [<buildsetting>=<value>]... [<buildaction>]...
xcodebuild [-project <projectname>] -scheme <schemeName> [-destination <destinationspecifier>]... [-configuration <configurationname>] [-arch <architecture>]... [-sdk [<sdkname>|<sdkpath>]] [-showBuildSettings] [<buildsetting>=<value>]... [<buildaction>]...
xcodebuild -workspace <workspacename> -scheme <schemeName> [-destination <destinationspecifier>]... [-configuration <configurationname>] [-arch <architecture>]... [-sdk [<sdkname>|<sdkpath>]] [-showBuildSettings] [<buildsetting>=<value>]... [<buildaction>]...
xcodebuild -version [-sdk [<sdkfullpath>|<sdkname>] [<infoitem>] ]
xcodebuild -list [[-project <projectname>]|[-workspace <workspacename>]] [-json]
xcodebuild -showsdks
xcodebuild -exportArchive -archivePath <xcarchivepath> -exportPath <destinationpath> -exportOptionsPlist <plistpath>
xcodebuild -exportLocalizations -localizationPath <path> -project <projectname> [-exportLanguage <targetlanguage>...]
xcodebuild -importLocalizations -localizationPath <path> -project <projectname>
複製代碼
你們這時候能夠新建一個項目Test
。而後在Xcode中,把公司項目(有證書)的Bundle Identifier
複製過來,這時候你會發現證書匹配經過了。(若是你沒有證書,那看回證書知識,弄好再往下看)有了這個項目,就能夠感覺這些命令了。
筆者認爲這方法不如方法二,並且蘋果也廢棄了其中一個工具。
先編譯出.app,而後轉成.ipa。
終端進項目文件夾後,先來試試第一條編譯命令。
xcodebuild -project Test.xcodeproj -target Test -configuration Release
。
不出意外,會打印以上文字,包括簽名身份和配置文件。文件夾下有Test/build/Release-iphoneos/Test.app.dSYM
。
這時咱們還要用xcrun
命令把其導出爲ipa文件
,(但xcrun在Xcode8.3廢棄了,若是還要用看這篇 xcrun: error: unable to find utility "PackageApplication", not a developer tool or in PATH)
處理好後,執行下面命令轉成ipa
。
xcrun -sdk iphoneos PackageApplication build/Release-iphoneos/Test.app -o ~/Desktop/Test.ipa
複製代碼
先用archive
,而後exprotArchive
,相似於手動打包的界面步驟。
(先運行xcodebuild -list
,記住Scheme)
終端進入項目文件夾後,運行xcodebuild archive -scheme Test -archivePath ~/Desktop/Test.xcarchive
,注意這裏不打scheme
會失敗。
筆者瞎猜以上和Xcode內打包對應着這個界面。
從上圖可看出,由於不一樣途徑發佈,因此要各自配置ExportOptions.plist
。也就是用於xcodebuild -exportArchive -archivePath <xcarchivepath> -exportPath <destinationpath> -exportOptionsPlist <plistpath>
中最後一個。
有兩種途徑配置。
ExportOptions.plist文件中有如下字段,配置以下:
method:字符串,爲打包的類型,分爲app-store,ad-hoc,enterprise和development,根據本身實際打包狀況填寫。
provisioningProfiles:字典,Xcode9須要,鍵值對爲{bundleid:描述文件名},描述文件名最好使用其對應的UUID。
signingCertificate:證書類型,開發環境爲iPhone Developer,生產環境爲iPhone Distribution。
signingStyle:自動仍是手動(manual與automatic),填寫manual便可。
stripSwiftSymbols:填寫爲YES。
teamID:爲開團隊ID,在鑰匙串中點擊證書詳情能夠查看到。
uploadBitcode:爲YES便可。
uploadSymbols:爲YES便可。
複製代碼
筆者仍是建議手動打包,複製過去再作修改(之後其餘項目只要稍微改動就能用,不用再次手動打包後複製)。由於經過圖形界面,能更好理解這些字段的意義以及對應的操做。
筆者選取了Enterprise
的截圖。其餘由於筆者沒有證書,就靠各位嘗試了。
而後終端中接着運行
xcodebuild -exportArchive -archivePath ~/Desktop/Test.xcarchive -exportPath ~/Desktop/Test.api -exportOptionsPlist ./ExportOptions.plist
複製代碼
xcodebuild學到這就會打包了,其餘不經常使用的方法,網上學習資源少,筆者也不想探究了。下面進入打包腳本。
筆者參考師兄@Tsui_YuenHong的文章關於 iOS 批量打包的總結,本身設置了一份腳本,用了蘋果建議的新方法以及補充了一些師兄腳本的不足點。
先說明一下筆者的悲慘遭遇。筆者之前也打過包上傳App-Store,整個過程愉愉快快。可是這項目,一共有20多個包,更新一次版本常常動不動就打十多個包。這樣打下來,頭髮就沒了。因爲代碼基本是同樣的,因此利用重簽名,能極大程度縮短打包時間。
簡單點說就是針對不一樣的用戶定製相應的自定義圖標、功能等。
defaults write
來修改項目中的 plist 文件,來達到修改 bundleName/bundleDisplayName等鍵值對,實現自定義App名字、展現名字功能,而且生成相應的plist文件。切換圖標的坑
先了解官方建議圖標尺寸。固然其餘尺寸,App圖標也會接受,自動適應。
Icon files (iOS 5)
(然而這個字段就是AppIcon???不知道底層還有什麼配置),筆者就不繼續嘗試了)。AppIcon的名字必定要對應上!由於後面命令行cp
時要所有替換,不然難以預測會出現什麼問題,就像下圖。(筆者的項目中,只弄了60@2x和60@3x的圖。)
打包出來後,AppIcon圖標在.app文件目錄中,不在BundleResources
中。
建議你們先看這篇文章。 iOS應用程序的重簽名(打包)
弄出來entitlements.plist,重簽名要用到。
題外話
筆者重簽名仍是遇到了坑,打包出來的軟件下載時進度條轉了一圈,但沒法最終完成。查了一段時間,才知道緣由是重簽名不成功。因此說腳本要重簽名失敗必須終止。
附帶一篇iTunes降級文章,,PP助手好像沒更新仍是什麼,只能用舊版iTunes來調試吧,真是累啊。將 iTunes 降回 12.6.3 可下載應用安裝包版本教程【Windows | Mac】
師兄的腳本一(運行時間256s)比筆者的腳本二(運行時間306s)快。
但腳本一採用的是蘋果廢棄的方法,之後出問題就試試腳本二吧。
兩種腳本不一樣之處在於:腳本一先出來.app,後出來.ipa;腳本二先出來Archive包(包裏有.app),後出來.ipa。
準備好Entitlements.plist
(本文有獲取教程,Cmd+f搜"重簽名要用到")。而且確保本機能運行xcrun(本文Cmd+f搜"在Xcode8.3廢棄")。
編譯後用xcrun導出ipa,最後重簽名。
腳本在師兄的文章關於 iOS 批量打包的總結裏貼出來了。
筆者在用該腳本時遇到圖標更換失敗的問題,和腳本無關,與項目配置有關,解決方法看回上面。
但筆者認爲該腳本存在一些問題的。例如重簽名等操做失敗後未終止腳本,致使筆者上傳到蒲公英後下載失敗一頭霧水。這問題很嚴重。不過只要適當判斷,加個exit
就能解決。
準備好Entitlements.plist
(本文有獲取教程,Cmd+f搜"重簽名要用到")和ExportOptions.plist
ist``(本文有獲取教程,Cmd+f搜"有兩種途徑配置")。
先用archive,而後exprotArchive(相似於手動打包流程),最後重簽名。
下面貼出腳本,注意裏面不少地方筆者用Project代替了。
# 1.Configuration Info
# 項目路徑 需修改
projectDir="你的項目路徑"
# 打包生成路徑 建議桌面
ipaPath="ipa生成路徑"
# 圖標路徑 需修改
iconPath="圖標路徑"
# 如下文件用於重簽名生成ipa,需修改
Entitlements=$ipaPath/Entitlements.plist
ExportOptions=$ipaPath/ExportOptions.plist
# 版本號
bundleVersion="2.0.0"
# 選擇打包序號 多選則以空格隔開 如("1" "2" "3")
appPackNum=("1" "2")
# 蒲公英分發參數 不分發可忽略 默認不分發 下面的兩個KEY是默認測試的網址對應KEY
ISUPLOAD=0
USERKEY="xxx"
APIKEY="xxx"
# ---------------------------可選 若是須要替換 app 的 icon --------------------------------- #
# 配置App信息數組 格式:"AppName(和工程中appInfo.Plist對應)" "icon" "Url中的AppName"(由於AppName爲中文,此處用英文)
#Schemes:
# 1.app1 app1Icon app1UrlName
# 2.app2 app2Icon app2UrlName
# 3.app3 app3Icon app3UrlName
# --------------------------------------------------------------------------------------- #
# 打包個數
appPackNumLength=${#appPackNum[*]}
appInfos=(
"app1" "app1Icon" "app1UrlName"
"app2" "app2Icon" "app2UrlName"
"app3" "app3Icon" "app3UrlName"
)
appInfosLength=${#appInfos[*]}
# Scheme Name
schemeName="xx"
# 開始時間
beginTime=`date +%s`
# 生成 xcarchive 路徑,建議桌面
mkdir ${ipaPath}/Payload
rm -rf ${ipaPath}/Payload/*
buildDir="${ipaPath}/Payload"
# 使用的時候要關掉自動簽名 改成手動簽名
# Build 生成 xcarchive
xcodebuild archive -workspace ${projectDir}/YouXiaoYun.xcworkspace -scheme ${schemeName} -archivePath ${buildDir}/Project.xcarchive
#
if [[ $? = 0 ]]; then # $? 表示上一條命令返回值。若是上一條命令成功執行,返回0,不然返回1.
echo "\033[31m 編譯成功\n \033[0m"
else
echo "\033[31m 編譯失敗\n \033[0m"
exit 0
fi
# 建立打包目錄
mkdir ${ipaPath}/AllPack
# 本地存放所有 IPA 的路徑
allIPAPackPath="${ipaPath}/allPack"
# 如下二選一
# 1.----所有打包----
#for (( i=0; i<appInfosLength; i+=3 )); do
# 2.----自定義打包----
for (( j=0; j<$appPackNumLength; j++)); do i=`expr ${appPackNum[$j]} - 1` i=`expr $i \* 3`
# App Bundle Name (CFBundleName)
appName=${appInfos[${i}]}
# App DisPlay Name
appDisplayName=${appInfos[${i}]}
# App Icon Name
appIconName=${appInfos[$i+1]}
# App Download Name
appDownloadName=${appInfos[$i+2]}
# 建立不一樣 app ipa 目錄
mkdir $allIPAPackPath/$appName
rm -rf $allIPAPackPath/$appName/*
echo "\033[31m appName:$appName appIconName:$appIconName appDownloadName:$appDownloadName\n \033[0m"
# 將對應的 icon 複製到須要修改的 app 的目錄下
cp -Rf $iconPath/$appName/* ${buildDir}/Project.xcarchive/Products/Applications/Project.app
if [[ $? = 0 ]]; then
echo "\033[31m $appName 修改 icon 成功\033[0m"
else
echo "\033[31m $appName 修改 icon 失敗\033[0m"
exit 0
fi
# 修改 Plist
defaults write $ipaPath/Payload/xx.app/info.plist "CFBundleName" $appName
defaults write $ipaPath/Payload/xx.app/info.plist "CFBundleDisplayName" $appDisplayName
if [[ $? = 0 ]]; then
echo "\033[31m $appName 修改 Plist 成功\033[0m"
else
echo "\033[31m $appName 修改 Plist 失敗\033[0m"
exit 0
fi
# 重簽名
xattr -cr ${buildDir}/Project.xcarchive/Products/Applications/Project.app
codesign -f -s "xx co., LTD" --entitlements $Entitlements ${buildDir}/Project.xcarchive/Products/Applications/Project.app
if [[ $? = 0 ]]; then
echo "\033[31m $appName 重簽名成功\n \033[0m"
else
echo "\033[31m $appName 重簽名失敗\n \033[0m"
exit 0
fi
# 生成 ipa
xcodebuild -exportArchive -archivePath $ipaPath/Payload/Project.xcarchive -exportPath ${ipaPath}/$appDownloadName.ipa -exportOptionsPlist $ExportOptions
if [[ $? = 0 ]]; then
echo "\033[31m \n $appName 生成 IPA 成功 \n\n\n\n\n\033[0m"
else
echo "\033[31m \n $appName 生成 IPA 失敗 \n\n\n\n\n\033[0m"
exit 0
fi
# 建立 Plist
plist_path=$allIPAPackPath/$appName/$appDownloadName.plist
cat << EOF > $plist_path
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>items</key>
<array>
<dict>
<key>assets</key>
<array>
<dict>
<key>kind</key>
<string>software-package</string>
<key>url</key>
<string>https://xxxxxxxxxxxx/$appDownloadName.ipa</string>
</dict>
<dict>
<key>kind</key>
<string>display-image</string>
<key>url</key>
<string>https://xxxxxxxxxxxx/${appIconName}.png</string>
</dict>
<dict>
<key>kind</key>
<string>full-size-image</string>
<key>url</key>
<string>https://xxxxxxxxxxxx/${appIconName}.png</string>
</dict>
</array>
<key>metadata</key>
<dict>
<key>bundle-identifier</key>
<string>你的bundid</string>
<key>bundle-version</key>
<string>$bundleVersion</string>
<key>kind</key>
<string>software</string>
<key>title</key>
<string>$appDownloadName</string>
</dict>
</dict>
</array>
</dict>
</plist>
EOF
# 移動
mv ${ipaPath}/$appDownloadName.ipa ${allIPAPackPath}/$appName
done
# 6.上傳蒲公英分發平臺
if [[ $ISUPLOAD = 1 ]]; then
echo "\n 開始上傳蒲公英... \n"
curl -F "file=@$AllIPAPackPath/$appName/$appDownloadName.ipa/Project.ipa" \
-F "uKey=$USERKEY" \
-F "_api_key=$APIKEY"\
http://www.pgyer.com/apiv1/app/upload
#判斷上傳結果
if [[ $? = 0 ]]; then
echo "\n ~~~~~~~\^o^/~~~~上傳到蒲公英成功~~~~\^o^/~~~ \n"
else
echo "\n ~~~~~\(╯-╰)/~~~~~~~上傳到蒲公英失敗~~~~~\(╯-╰)/~~~~~ \n"
fi
fi
# 清除無關文件
rm -rf $ipaPath/Payload
# 結束時間
endTime=`date +%s`
echo -e "打包時間$[ endTime - beginTime ]秒"
複製代碼