特别说明:如果项目没有采用Cocoapods管理,没有.xcworkspace,只有xcodeproj;只需要将脚本中这句
xcodebuild \
archive -workspace ${project_path}/${project_name}.xcworkspace \
这句替换成下面这样就ok了
xcodebuild \
archive -project ${project_path}/${project_name}.xcodeproj \
日常编译打包工作主要是以下两个目的:
提交测试版本ipa给测试人员
配置好测试描述文件,然后Product -> Archive编译打包,选择Organizer,导出ad hoc 的 ipa包。再上传到Fir等第三方平台上,然后通知测试同事进行测试。整个流程下来需要人工监守操作比较耗费时间。
提交ipa包到App Store已供审核
配置好正式的描述文件,然后同样的方式打包导出app store 的 ipa包。通过Application Loader 等方式提交到App store等待苹果处理二进制包,处理完后选择构建版本,最后提交等待苹果审核。
无论打测试包提供测试人员测试还是打正式包上传到App strore,整个过程都是重复耗费人工的操作,需要人工等待,然后各种点击选择...我们可以通过编写脚本语言来实现整个过程。
配置自动打包发布的流程
通过下面几步的设置好之后,以后再进行打包发布到第三方平台或者App Store 只需要一步就能搞定了(一个回车搞定)
笔者通过shell脚本实现从archive->生成ipa->上传到第三方平台(Fir.im 、蒲公英)或 App store。通过下面几步即可实现自动打包上传功能。
将archiveScript中的几文件拖入工程的根目录
根据自己需求选择好描述文件
根据自己的项目修改一下shell.sh (修改哪里下面会指出)
cd到工程根目录,通过./shell.sh 执行脚本即可
下面通过实例详细演示整个过程
第一种:打包上传到第三方平台Fir (上传蒲公英原理一样)
第二种:打包上传到App store
将通过这几步来讲解整个过程
准备工作
准备工作做完后,正式开启自动化之路
自动化脚本执行过程中可能遇到的错误
准备工作
因为要上传到Fir平台,需要先安装fir-cli
![](https://img.haomeiwen.com/i2470124/ac5293323f51cd66.png)
安装fir-cli
如果没有安装过rvm,需要安装rvm,在终端输入rvm -v命令查看,如果打印出rvm:command not found说明没有安装过rvm,如果能打印出rvm版本等信息说明安装过。如果没有安装过rvm可以通过下面的命安装,如果已经安装过可以忽略。
在终端输入curl -L get.rvm.io | bash -s stable,然后稍等一会rvm就安装好了
在终端输入source ~/.bashrc
在终端输入source ~/.bash_profile
再输入rvm -v查看安装成功
准备工作做完后,正式开启自动化之路
一、将archiveScript中的3个文件拖入工程的根目录
![](https://img.haomeiwen.com/i2470124/bf6f81306c27ccdd.png)
Snip20170922_61.png
二、根据自己需求选择好描述文件
![](https://img.haomeiwen.com/i2470124/76095469593aef38.png)
Snip20170922_53.png
三、修改一下shell.sh 文件
![](https://img.haomeiwen.com/i2470124/71a8d3042430f837.png)
修改1
![](https://img.haomeiwen.com/i2470124/1b524cf55d59ce86.png)
修改2
![](https://img.haomeiwen.com/i2470124/d4cfd69a6f3d2e37.png)
自己工程的project_name名字
Product ->Scheme -> Edit Scheme 查看自己的scheme_name
![](https://img.haomeiwen.com/i2470124/b37b9231ff3f365c.png)
scheme_name
获取Fir平台的token
![](https://img.haomeiwen.com/i2470124/22b696fae8c98f4d.png)
Snip20170922_50.png
三、 cd到工程根目录,./shell.sh 回车就会执行脚本
![](https://img.haomeiwen.com/i2470124/f6a23eb4dd4bc0e4.png)
执行脚本
四、 根据自己的需求选择即可
![](https://img.haomeiwen.com/i2470124/8eee60e4dd742b49.png)
Snip20170922_63.png
如果开始选择的1:app-store 会发布到app store
![](https://img.haomeiwen.com/i2470124/1d1e291cd7bc289d.png)
发布app store 成功
如果开始选择的2:ad-hoc 发布到fir平台
![](https://img.haomeiwen.com/i2470124/755b7f0111d49b8a.png)
Snip20170922_65.png
如果遇到下面的错误
![](https://img.haomeiwen.com/i2470124/3e9af5a8ac95d5ac.png)
Snip20170922_56.png
解决方法:在终端 输入rvm system后重新执行sehll脚本就可以了
![](https://img.haomeiwen.com/i2470124/7090b818bc135b3a.png)
Snip20170922_57.png
如果前面已经安装过fir-cli,但是在脚本执行过程中任然报fir:command not found的错误
解决办法: 在终端输入rvm get head
![](https://img.haomeiwen.com/i2470124/aceb1efaa51925b1.png)
Snip20170922_66.png
执行完毕后再次执行脚本就ok了
到这里就已经实现了通过脚本打包并发布到第三方平台Fir 和 Appstore的整个流程。接下来对shell中的脚本和一些自动化原理进行简单说明
shell中的脚本和一些自动化原理
正常情况下手动在Xcode中执行Product -> Archive, 在Xcode底层是通过xcodebuild相关的命令编译、打包生成ipa包的.(xcodebuild主要是用来编译,打包成Archive和导出ipa包)
进入终端可以通过下面的命令查看一下xcodebuild的version
![](https://img.haomeiwen.com/i2470124/8dc971518a3b38b7.png)
Snip20170925_1.png
接下来,看一下Shell脚本
![](https://img.haomeiwen.com/i2470124/15ee6629db49c988.png)
设置变量
![](https://img.haomeiwen.com/i2470124/7dcd5c261933c8d7.png)
选择输入
上面内容注释大家一看应该就明白
![](https://img.haomeiwen.com/i2470124/718fd87c190499a7.png)
clean并archive
![](https://img.haomeiwen.com/i2470124/bd8bfee14570444b.png)
导出ipa
清理构建目录
xcodebuild \
clean -configuration ${development_mode}
编译之前先clean下,就如同在Xcode进行Product -> Clean。
编译打包成Archive
xcodebuild \
archive -workspace ${project_path}/${project_name}.xcworkspace \
-scheme ${scheme_name} \
-configuration ${development_mode} \
-archivePath ${build_path}/${project_name}.xcarchive
编译工程,编译并生成.xcarchive文件,放在build_path下,名字是project_name.xcarchive,就如在Xcode进行Product -> Archive这一步最为耗时.
将Archive导出ipa
xcodebuild -exportArchive -archivePath ${build_path}/${project_name}.xcarchive \
-configuration ${development_mode} \
-exportPath ${exportIpaPath} \
-exportOptionsPlist ${exportOptionsPlistPath}
将生成的.xcarchive文件导出.ipa包到指定的exportIpaPath路径下。
说明:
用\来进行换行分隔,一条shell命令过长时可以进行分割显示.
$变量名是引用变量,拿来使用
|| exit 指明如果这一条命令执行失败,则退出当前shell.
![](https://img.haomeiwen.com/i2470124/f16fde193789cb9e.png)
Snip20170925_10.png
通过Fir-cli命令上传到Fir平台
# 将XXX替换成自己的Fir平台的token
fir login -T XXX
fir publish $exportIpaPath/$scheme_name.ipa
通过altool工具提交ipa包到app store
这个工具实际上是Application Loader,打开Xcode-左上角Xcode-Open Developer Tool-Application Loader可看到
altool的路径是:
/Applications/Xcode.app/Contents/Applications/Application\ Loader.app/Contents/Frameworks/ITunesSoftwareService.framework/Support/altool
#验证并上传到App Store
# 将-u 后面的XXX替换成自己的AppleID的账号,-p后面的XXX替换成自己的密码
altoolPath="/Applications/Xcode.app/Contents/Applications/Application Loader.app/Contents/Frameworks/ITunesSoftwareService.framework/Versions/A/Support/altool"
"$altoolPath" --validate-app -f ${exportIpaPath}/${scheme_name}.ipa -u XXX -p XXX -t ios --output-format xml
"$altoolPath" --upload-app -f ${exportIpaPath}/${scheme_name}.ipa -u XXX -p XXX -t ios --output-format xml
![](https://img.haomeiwen.com/i2470124/33b8861231ef3e89.png)
Snip20170923_69.png
![](https://img.haomeiwen.com/i2470124/b46abaa79e4ef5ff.png)
Snip20170923_70.png
整个过程和原理还算比较简单,shell脚本还是满有意思的,作为苹果开发人员,有必要学习一下,本人也刚学习shell 不久,欢迎大家交流。
参考文档:
http://www.jianshu.com/p/bd4c22952e01
作者:JiaJung
链接:http://www.jianshu.com/p/05dc9f925467
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
以上 一般情况下 在无git管理工具情况下 可正常执行 如项目已git管理 会出现 不允许执行的警告 需要给 .sh 脚本文件添加权限 即使 在 ls-l的时候 是有权限的 需要再次添加
zsh ./test.sh 这样的情况会执行的
chmod +x ./test.sh #使脚本具有执行权限
网友评论
2018-03-29 14:17:53.480 xcodebuild[50600:2683252] [MT] IDEDistribution: Step failed: <IDEDistributionOptionsStep: 0x7fe20e370dd0>: Error Domain=IDEFoundationErrorDomain Code=1 "exportOptionsPlist error for key 'uploadBitcode': cannot upload bitcode because bitcode is imbalanced" UserInfo={NSLocalizedDescription=exportOptionsPlist error for key 'uploadBitcode': cannot upload bitcode because bitcode is imbalanced}
error: exportArchive: exportOptionsPlist error for key 'uploadBitcode': cannot upload bitcode because bitcode is imbalanced
Error Domain=IDEFoundationErrorDomain Code=1 "exportOptionsPlist error for key 'uploadBitcode': cannot upload bitcode because bitcode is imbalanced" UserInfo={NSLocalizedDescription=exportOptionsPlist error for key 'uploadBitcode': cannot upload bitcode because bitcode is imbalanced}
** EXPORT FAILED **