songxinfang's blog


learning work communicate


多target工程搭建及批量打包ipa

背景前言

应产品需求要生产一批非常相似的考试学习工具App,虽然针对不同的人群或者职称职位去生产不同的App,但是核心功能与UI布局基本一致,只是可能会有细微的图标、文本标签的不同,这种情况下如果说全部搭建project复制大量的代码会非常不利于后期的维护与修改,所以采用苹果提供的多target方案是非常行之有效的最优方案了

需求分析

那么每个App与App之间到底有哪些地方是完全没有差异的是可以完全复用的,又有哪些代码、资源是不同的需要一个怎样的方案去解决编码甚至提高效率的呢,下面需要具体分析了

应用相同点

  1. 整个业务流程、核心功能完全一样
  2. UI布局甚至用色都完全一致,即工程配置的大部分切图都是同一套
  3. 后期版本迭代提出的需求会要求所有App一致更新

从这些相同点可以总结出,工程代码基本是可以全套复用的

应用差异点

  1. AppName、AppBundleId
  2. AppIcon、LaunchImage
  3. 少量文案、URL、第三方key
  4. 少量切图、数据库db等资源文件

以上不同的差异需要不同的方案来解决,下面我讲根据相同的顺序给出我的解决方式

差异点配置方案

  1. 每个target的general Identity配置AppName、AppBundleId
  2. 每个target配置general下App Icon and Launch Images选择正确的Assets文件夹
  3. project专门管理一个plist文件,根据不同的App配置相关的文案、URL、key等
  4. 相同功用的切图、db用一样的名称,放在自己target命名下的文件夹里,也就是同类资源路径不同,然后分别在每个target配置build Phases下的copy Bundle Resources只添加自己路径下的资源

多target工程搭建

  1. 完善核心功能核心代码,生产出第一个完整的App
  2. duplicate多target,配置关键内容
  3. 每duplicate出一个target就会对应的多出一个scheme,但是名称是自动生成的,我们可以通过duplicate方式修改scheme的名称与target名称一致或者关联

自动化批量打包ipa

多target工程当然可以使用xcode逐个打包,但是出于好奇以及未来可能会实用的一项技术,我还是花时间去研究了自动化批量打包技术,最后终于写出了自己的第一份有实际意义的shell脚本😄

记录一下整个研究过程,首先了解几个简单命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#打印工程目录下的targets、workspace下的schemes等信息
xcodebuild -list
#清空编译文件
/usr/bin/xcodebuild -target targetName clean
#build the target
/usr/bin/xcodebuild -target targetName
#导出ipa包
/usr/bin/xcrun -sdk iphoneos PackageApplication -v build/Release-iphoneos/AppName.app -o path/AppName.ipa
#workspace archive方式生成xcarchive文件
xcodebuild archive -workspace workspace.xcworkspace -scheme schemeName -archivePath path/AppName.xcarchive
#workspace archive方式导出ipa没有签名无法安装真机
/usr/bin/xcrun -sdk iphoneos PackageApplication -v path/AppName.xcarchive/Products/Applications/AppName.app -o path/AppName.ipa
#签名并打包ipa可以安装到真机
xcodebuild -exportArchive -archivePath path/AppName.xcarchive -exportPath path/AppName -exportFormat ipa -exportProvisioningProfile "iOS Team Provisioning Profile: com.xywy.xxxxxxxx"

生成只能打一个包的脚本

1
2
3
4
5
6
7
8
#方式1
/usr/bin/xcodebuild -target targetName clean
/usr/bin/xcodebuild -target targetName
/usr/bin/xcrun -sdk iphoneos PackageApplication -v build/Release-iphoneos/AppName.app -o path/AppName.ipa
#或者方式2
xcodebuild archive -workspace workspace.xcworkspace -scheme schemeName -archivePath path/AppName.xcarchive
/usr/bin/xcrun -sdk iphoneos PackageApplication -v path/AppName.xcarchive/Products/Applications/AppName.app -o path/AppName.ipa

生成打多个包的脚本:手动输入所有schemes并打包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/bash
project_path=$(pwd)
scheme_name[0]=DoctorBuestionBank
scheme_name[1]=NewDoctorBuestionBank
for scheme_name in ${scheme_name[*]}
do
echo ${scheme_name}
#clean 工程
/usr/bin/xcodebuild -target ${scheme_name} clean
#生产xcarchive
xcodebuild archive -workspace DoctorBuestionBank.xcworkspace -scheme ${scheme_name} -archivePath ${project_path}/${scheme_name}.xcarchive
#生产ipa
/usr/bin/xcrun -sdk iphoneos PackageApplication -v ${project_path}/${scheme_name}.xcarchive/Products/Applications/${scheme_name}.app -o ${project_path}/${scheme_name}.ipa
done

自动化批量打包:自动读取schemes并打包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#!/bin/bash
# author:songxinfang
#读取工程配置所有的targets,然后编译打包
xcodebuild -list > file1
i=0
while read line
do
if [[ $line = "Targets:" ]];
then
tag=1
elif [[ $tag == 1 && ${#line} == 0 ]];
then
break
elif [[ $tag == 1 ]];
then
scheme_array[$i]=$line
let i=i+1
fi
done<file1
echo ${scheme_array}
project_path=$(pwd)
for scheme_name in ${scheme_array[*]}
do
#clean 工程
/usr/bin/xcodebuild -target ${scheme_name} clean
#生产xcarchive
xcodebuild archive -workspace DoctorBuestionBank.xcworkspace -scheme ${scheme_name} -archivePath ${project_path}/${scheme_name}.xcarchive
#生产ipa
/usr/bin/xcrun -sdk iphoneos PackageApplication -v ${project_path}/${scheme_name}.xcarchive/Products/Applications/${scheme_name}.app -o ${project_path}/${scheme_name}.ipa
done