iOS 多个环境一次打包

概述

偶然看到一个很有趣的问题:如何在ios环境下实现多个环境同时打包。

谈到多环境,我想大多公司都至少有2-3个环境,比如Test环境,UAT(User Acceptance Test)用户验收测试环境,Release环境等等。当需要开发打多个包的时候,一般常见做法就是直接代码里面修改环境变量,改完之后Archive一下就打包了。或者在App中内置一个切换的按钮,实现环境的切换。

或者,你们公司已经搭建了Jenkins环境,利用Jenkins环境就可以给app来配置一下多个环境变量,之后Jenkins分别再不同环境下自动集成即可。

那么如何实现ios的多环境打包呢?参照网上的一些方案这里做一个简单的总结。要实现多环境打包,现在主流的方案有三种(各有优劣)。

1.利用Build Configuration来配置多环境

2.利用xcconfig文件来配置多环境

3.利用Targets来配置多环境

一、Build Configuration方式

做过ios开发的人都知道Build Configuration,系统默认提供2个环境,一个Debug,一个Release。这里,我们利用的就是Build Configuration给我们提供的配置功能来实现多环境打包。具体步骤如下:

1,新建Build Configuration

点击Project里面找到Configuration,然后选择添加一个Configuration,系统默认是2个,一个Debug,一个Release。这里我们需要选择是复制一个Debug还是Release。Release是不能调试程序,因为默认是屏蔽了可调试的一些参数。


20170717103707845.jpeg

这里我们新增一套环境:Configuration。在这一套包含了一些编译参数的配置集合。如果此时项目里面有cocopods的话,打开Configuration Set就会发现是如下的样子。


20170717104056461.jpeg

然后打开项目的pod文件,打开配置是会看到如下信息:
20170717104217603.jpeg

说明:pod安装完成之后会自动生成xcconfig文件,如果你手动新建这个xcconfig,然后把原来的debug和release对应的pod xcconfig文件内容复制进来,这样做是无效的,需要pod自己去生成xcconfig文件才能被识别到。

新建完Build Configuration,这个时候需要新建pod里面对应的Build Configuration,要不然一会编译会报错。如果没用pod,可以忽略一下这一段。


20170717104400404.jpeg
2,新建Scheme

20170717104508168.jpeg

新建完成之后,我们就可以编辑刚刚新建的Scheme,我们可以把Run模式和Archive都改成新建Scheme。
20170717104623591.jpeg

注意:如果是使用了Git这些协同工具的同学这里还需要把刚刚新建的Scheme共享出去,否则其他人看不到这个Scheme。
20170717104714778.jpeg

3,新建User-defined Build Settings

回到Project的Build Settings里面来,Add User-Defined Setting。

20170717105115264.jpeg

CustomAppBundleld是为了之后打包可以分开打成多个包,这里需要3个不同的Id,建议是直接在原来的Bundleld加上Scheme的名字即可。CustomProductName为app显示在手机上的名字,建议直接按环境给予描述,例如:测试(debug),线上(relase),UAT等。
20170717105322581.jpeg

需要注意的是:Pods的Build_DIR这些目录其实是Pods自己生成好的,之前执行过Pod install 之后,这里默认都是配置好的,不需要再改动了。

4,修改info.plist文件 和 Images.xcassets

打开info.plist文件。由于我们新添加了2个CustomAppBundleld 和 CustomProductName,这里我们需要把info.plist里面的Bundle display name修改成我们自定义的这个字典。编译过程中,编译器会根据我们设置好的Scheme去自己选择Debug,Release,TestRelease分别对应的ProductName。




为了方便区分不同的环境,你还可以对不同环境下App Icon,名字等做一个修改。

既然我们已经新建了这几个scheme,那接下来怎么把他们都打包成app呢?

这里分享下实际打包过程中的一些经验。

每个环境都要设置好Debug 和 Release!!!

千万别认为线上的版本只设置Release就好,哪天需要调试线上版本,没有设置Debug就无从下手了。也千万别认为测试环境的版本只要设置Debug就好,万一哪天要发布一个测试环境需要发Release包,那又无从下手了。我的建议就是每个环境都配置Debug 和 Release。

在打包的时候,一定要注意将Scheme的名字和编译方式区分开。选择一个Scheme,只是相当于选择了一个环境,并不是代表这Debug还是Release。


20170717110144760.jpeg

配置好上述之后,就可以选择不同环境运行app了。可以在手机上生成不同的环境的app,可以同时安装。


20170717110324703.jpeg

接下来说几种动态配置环境变量的方法。
动态配置环境变量

使用GCC预编译头参数GCC_PREPROCESSOR_DEFINITIONS
进入到Build Settings里面,可以找到Apple LLVM Preprocessing,找到Preprocessor Macros,在这里我们是可以加一些环境变量的宏定义来标识符。Preprocessor Macros可以根据不同的环境预先制定不同定义的宏。

20170717110621421.jpeg

使用plist文件动态配置环境变量

首先,新建3个名字一样的plist作为3个环境的配置文件(新建三个配置文件,分别放在3个不同文件夹下面即可)。


20170717110945047.jpeg

接下来我们要做的是在编译的时候(运行app前),动态的copy Configuration.plist到app里面,这里需要设置一个copy脚本。


20170717111122742.jpeg

进入到我们的Target里面,找到Build Phases,我们新建一个New Copy Files Phase,并且重命名为Copy Configuration Files。其中,脚本能保证我们的Configuration.plist 文件可以在编译的时候,选择其中一个打包进入app。再通过读取这个plist里面的信息就可以做到动态化。
使用单例来处理环境切换

当然使用一个单例也可以做到环境切换。新建一个单例,然后可以在设置菜单里面加入一个列表,里面列出所有的环境,然后用户选择以后,单例就初始化用户所选的环境。

二、利用xcconfig文件配置多环境

提到xcconfig,就要先说说几个概念。Xcode Workspace、Xcode Scheme、Xcode Project、Xcode Target、Build Settings 。

Xcode Project

project就是一个个的仓库,里面会包含属于这个项目的所有文件,资源,以及生成一个或者多个软件产品的信息。每一个project会包含一个或者多个 targets,而每一个 target 告诉我们如何生产 products。project 会为所有 targets 定义了默认的 build settings,每一个 target 也能自定义自己的 build settings,且 target 的 build settings 会重写 project 的 build settings。

Xcode Project 文件会包含以下信息,对资源文件的引用(源码.h和.m文件,frame,资源文件plist,bundle文件等,图片文件image.xcassets还有Interface Builder(nib),storyboard文件)、文件结构导航中用来组织源文件的组、Project-level build configurations(Debug\Release)、Targets、可执行环境,该环境用于调试或者测试程序。

Xcode Target

target 会有且唯一生成一个 product, 它将构建该 product 所需的文件和处理这些文件所需的指令集整合进 build system 中。Projects 会包含一个或者多个 targets,每一个 target 将会产出一个 product。需要注意的是, Project 可以包含多个 target, 但是在同一时刻,只会有一个 target 生效,可用 Xcode 的 scheme 来指定是哪一个 target 生效。

Build Settings

build setting 中包含了 product 生成过程中所需的参数信息。project的build settings会对于整个project 中的所有targets生效,而target的build settings是重写了Project的build settings,重写的配置以target为准。

一个 build configaration 指定了一套 build settings 用于生成某一 target 的 product,例如Debug和Release就属于build configaration。

Xcode Scheme

一个Scheme就包含了一套targets(这些targets之间可能有依赖关系),一个configuration,一套待执行的tests。

xcconfig使用

1,新建一个xcconfig文件,然后在project设置一下。



20170717121203902.jpeg

接下来,把配置文件换成我们刚刚新建的文件。细心的读者可能发现,其实我们一直使用的cocopods就是用这个文件来配置编译参数的。

GCC_PREPROCESSOR_DEFINITIONS 是 GCC 预编译头参数,通常我们可以在 Project 文件下的 Build Settings 对预编译宏定义进行默认赋值。

在Build Settings里面的 Apple LLVM 7.X - Preprocessing - Preprocessor Macros 。


20170717121647562.jpeg

Preprocessor Macros 其实是按照 Configuration 选项进行默认配置的, 它是可以根据不同的环境预先制定不同定义的宏,或者为不同环境下的相同变量定义不同的值。

在xcconfig 我们可以写入不同的 Configuration 选项配置不同的文件。每一个 xcconfig 可以配置 Build Settings 里的属性值, 其实实质就是通过 xcconfig 去修改 GCC_PREPROCESSOR_DEFINITIONS 的值,这样我们就可以做到动态配置环境的需求了。

现在本地有这么多配置,到底哪一个最终生效呢?打开Build 里面的level,优先级是从左往右,依次降低的。Resolved = target-level > project-level > 自定义配置文件 > iOS 默认配置。


20170717121849444.jpeg

除了上面的功能以为,还能利用xcconfig动态配置Build Settings里面的很多参数。这其实类似于cocopods的做法。详情资料请大家自行搜索。

三、利用Targets配置多环境

其实使用Scheme和xcconfig就可以实现多环境的功能,使用Targets反而显得更加麻烦。利用Targets可以瞬间大批量产生大量的app。相关使用可以查看:使用多Target来构建大量相似App

仅仅只用一套代码,就可以生产出7个app。7个app的证书都是不同的,配置也都不同,但是代码只需要维护一套代码,就可以完成维护7个app的目标。

下面来看一下如何使用Targets来生成不同的app。


20170717140246032.png

一种方法是完全新建一个Targets,另外一种方法是复制原有的Targets。

其实第一种方法建立出Targets,之后看你需求是怎么样的。如果也想是做OEM这种,可以把新建出来的project删掉,本地还是维护一套代码,然后在新建的Targets 的Build Phases里面去把本地现有代码加上,参数自己可以随意配置。这样也是一套代码维护多个app。

第二种方法就是复制一个原有的Targets,这种做法只用自己去改参数就可以了。

再来说说Targets的参数。

由于我们新建了Targets,相当于新建了一个app了。所以里面的所有的文件全部都可以更改。包括info.plist,源码引用,Build Settings……所有参数都可以改,这样就不仅仅局限于修改Scheme和xcconfig,所以之前说仅仅配置一个多环境用Targets有点兴师动众,但是它确实能完成目的。根据第二章里面我们也提到了,Targets相当于流水线,仅次于Project的地位,可以想象,有了Targets,我们没有什么不能修改的。

注意点

在开发过程中遇到比较坑爹的问题:证书不使用xcode的Automatically manage signing 的时候,(环境不同bundle ID不同的时候)每个版本选择不同的描述文件,需要注意的地方 bundle IDBuild SettingsPackage分栏下的Product Bundle Identifier的为准,要不然选择描述文件的时候有问题,就会提示
The provisioning profile specified in your build settings ("xxx") has an AppID of "com.xxx" which does not match your bundle identifier "com.xxx"
http://blog.csdn.net/l2i2j2/article/details/51661443

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容