iOS 多target创建和打包

由于公司需要,需有一套代码出多个APP,(有企业版也有Store版),同时企业版又分多个渠道(二维码放在不同的地方推广),由于企业版和Store版证书App的Logo、启动图、友盟、支付、分享scheme什么的都不相同,一套代码出好几个app,外加几个渠道,一次打近十个包,改到很来多时候自己都蒙了,所以为了不出错,也是为了不头疼所以就只能想想解决办法。

                                                            一个自动打包脚本是多么的重要.pic.jpg

1.多target

2.buildSetting中设置不同的宏,以区分是哪个target

3.将channel字断加入到plist中,以区分多版本

4.PlistBuddy修改plist(version及channel)

5.打包脚本

一、多target

如果只是一套代码多个APP可以创建多个target,每个target一套配置文件

                                                                                 添加target.jpg

                                                                                三处修改.jpg

1.点击工程

2.右键target点击Duplicate

3.修改target名称、修改plist名称、修改scheme(点击上图3处选择EditScheme->MamagerScheme,修改一下名称)

                                                                              修改Scheme.jpg

4.添加宏代码中通过判断是否定义了该宏来判断当前是哪个target

                                                                                   添加宏.jpg

5.如果你是swift和oc混编的工程interfaceHeader原来是一个配置的值,由于改了target名称回导致新建的target找不到这个文件,所以要这个配置值改为固定值

                                                                             修改interfaceHeader.jpg

6.代码中判断当前是哪个target

#ifdef HSENTERPRISE

 //hs

#elif defined XUETUENTERPRISE

//xuetu

#endif

二、多渠道

多渠道主要是给每个app加一个标识符,以区分是哪个渠道,我们是在每次网络请求时都会上传当前channel,用以统计每个渠道的注册量或者购买等,这里channel字段要加在plist当中,通过自动脚本打包,每次修改一下channel字段,生成对应的ipa包。不然手动改真的爆炸。

                                                                    将channel字段加入到plist中.jpg

每个target都有对应的一个info-plist,所以我们可以通过以下方法获取到当前target绑定的plist,从而获取channel,当然上面通过宏来判断是哪个target,也可以在plist文件加一个标识符来区分是哪个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

创建数组

/usr/libexec/PlistBuddy -c "add :arrayname array " /Users/hsedu/Desktop/hskaoyanStrore-Info.plist

为数组增加值

/usr/libexec/PlistBuddy -c "add :arrayname:0 string lisi " /Users/hsedu/Desktop/hskaoyanStrore-Info.plist

四、自动打包脚本

1、shell几个常用语句

定义变量

APPVERSION="2.1.7"

For in循环(变量无需声明直接用)

archiveIpas="  vkeEnterprise xuetuEnterprise vkeStore hsStore";for produce in $archiveIpasdo#codingdone

函数及case($1代表传入的参数)

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,从而判定是企业版还是stroe版证书if [[ $produce == *$B* ]]thenmethodString="enterprise"#包含elsemethodString="ad-hoc"#不包含fi

2.xcodebuild 打包

需要哪些准备

teamID

可以在appleDevelop账号的Membership Details中查看开发账号的teamID

可以在project文件显示包内容中的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在工程内,不含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 名称

-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证书名称

                                                                                证书名称.png

PROVISIONING_PROFILE描述文件UUID

进入描述文件查看UUID.png

                                                                                  UUID.png

4.导出ipa包

#导出ipaxcodebuild -exportArchive -archivePath "${archiveProducePath}${produce}${channel}.xcarchive"  -exportPath "${ipaProducePath}${produce}${channel}"  -exportOptionsPlist "$optionsPlist_FILE_PATH"

-archivePath刚才生成的archive文件路径

-exportPathipa包导出路径

-exportOptionsPlist导出相关配置的plist

                                                                  exportOptionsPlist.png

可以通过修改method参数来选择你要的包是adhoc还是企业版或者是store(不通包所需的描述文件不同)

5.自动打包脚本最终版

#!/bin/bashecho "      _          ------ _                  "echo "    (_)        / /    ) )      ___        "echo "    / /        / /    ) )      / __ \      "echo "  / /        / /__ _)_)      / /_/ /\      "echo "  /_/        /_/              \____/\ \    "#hsEnterprise xx企业版#hsStore      xxStore版#vkeEnterprise  Vx企业版#vkeStore        xxStore版#xuetuEnterprise    x途企业版#*****************************************设置区域**********************************************##设置archive生成的.xcarchive文件路径(绝对路径)archiveProducePath="/Users/hsedu/Desktop/ipa/"#设置ipa包生成路径(绝对路径)ipaProducePath="/Users/hsedu/Desktop/ipa/"#设置Plist文件路径前半部分部分(后半部分需要动态拼接)infoPlist_HEAD_PATH=$(pwd)#设置exportOptions.plist文件路径optionsPlist_FILE_PATH="$(pwd)/exportOptions.plist"#APP版本号APPVERSION="2.1.7"#设置是打测试版还是发布版本(Release or Debug)configuration="Release"#设置为哪些App打包ipa hsEnterprise vkeEnterprise xuetuEnterprise vkeStore hsStorearchiveIpas=" 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 $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,从而判定是企业版还是stroe版证书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"#设置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-没用cocoaPods或者cocoaPods在工程内,不含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#导出ipaxcodebuild -exportArchive -archivePath "${archiveProducePath}${produce}${channel}.xcarchive"  -exportPath "${ipaProducePath}${produce}${channel}"  -exportOptionsPlist "$optionsPlist_FILE_PATH"donedoneprintf "\n(-_-)-Complete-(-_-)\n\n"exit 0

注意

现在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不能用,出现rvm use ...、rvm找不到等问题,那就是使用的rvm或者rvm路径不正确,导致使用的默认ruby有问题,这里需要使用系统的ruby,需要查看本机rvm。个人遇到的问题是,本机rvm路径有问题,PATH里面的rvm路径也有问题,找不到正确的rvm以及ruby。unset rvm 清空PATH,重新添加相关路径(source /ect/paths)即可,删除rvm(不需要rvm,rvm system不能用就删除rvm不需要),重启。

如果工程中某个target报某个类没有找到,那一定是创建类的时候忘记勾选targt了,(我这是git两个分支合并的时候运行报的xxx这个类找不到)

点击这个类,右边类的属性中target memberShip勾选一下即可

                                                                 勾选一下即可.pic.jpg

你可能感兴趣的:(iOS 多target创建和打包)