这里我们会介绍三种,在充分了解前两种的基础上,建议大家在开发中灵活使用第三种方法。当然,大家在熟练的情况也可以根据实际情况自己组合使用
在讲解多环境配置之前我们先来认识一下,我们在Xcode常见的一些名词,都代表什么意思?
-
Project
:包含了项目所有的代码,资源文件,所有信息。 -
Target
:对指定代码和资源文件的具体构建方式。 -
Scheme
:对指定Target的环境配置。
首先我们来看一个熟悉的东西:
相信大家都会通多上面修改Configuration
的方式来切换Debug
和Release
的开发环境。但是仅仅是这样并不能满足我们日常的开发需求,下面我们来介绍三种Xcode的多环境配置,希望可以在日常的开发中给大家带来方便,增加效率。
方法一:通过增加Target
我们知道,Target
是对指定代码和资源文件的具体构建方式。那么理论上我们知道复制一份Target
出来,然后在不同的Target
下,设置不同的参数配置不就可以了吗!
下面我们来配置一下:
1、首先我们针对对应的Target
,制作一个副本
2、制作完成之后,我们会发现工程里面多了一个
Target
和一个Info.plist
文件,同时也会多一个Scheme
。3、我们可以通过修改Bundle Indentifier
、Info.plist
和Scheme
名称来进行区分
⚠️ 注意,修改外Info.plist
文件名之后,一定要在对应的Build Settings
里面修改Info.plist
路径
- 我们接着讲一下,
Target
中预定义宏的的设置
我们再testDebug
中设置自定义的宏:
使用如下:
if (TEST_DEBUG) {
NSLog(@"Debug");
} else {
NSLog(@"Release");
}
注意 ⚠️ :此时TEST_DEBUG
我们并不能在test
中使用,因为我们只在testDebug
设置了;那么当我们切换到test
环境中的时候,就会报错:(这里要注意,对个Target
操作的只有一套代码)
这时候我们只需要在
test
环境下也设置同样名字的宏就可以了,宏对应的值设置成不同的,就可以在代码里面区分不同的环境,执行不同的指令了。
-
Swift环境中设置
Other Swift Flags
,混编情况下也是一样。
我们在上面工程的基础上看下混编要怎么设置(注意,视情况做出调整):
这里要注意,在添加宏
一定要在前面加一个-D
方法二:添加Scheme
然后我们可以对不同的
Scheme
配置不同的configuration
来进行环境区分。如下:这样我们就可以通过切换不同的
Scheme
来切换不同的开发环境。
-
举个例子,不同的
Scheme
对应不同的AppIcon
:
首先我们要在Assets.xcassets
再添加一个AppIcon
:
接着我们可以在target
的Build Settings
里面设置不同的configuration
对应不同的AppIcon
:
-
我们还可以针对不同
Scheme
设置不同的App Name
:
在Target
的Build Settings
里面添加自定义的字段,如下:
假设我们现在就将字段名定义为BUNDLEDISPLAY_NAME
,然后Debug
模式下就叫Debug
,Release
模式下就叫Release
。
接着我们要在Info.plist
文件中替换Bundle name
:
效果如下:
缺点:此时同样的,我们还是需要在
Target
里面修改很多东西,这样的还难免会遗漏一些东西,改起来也不是特别的方便。
方法三:利用xcconfig
文件,结合自定义的Scheme
来配置多环境开发
- 首先我们来了解一下什么是
xcconfig
文件,我们在使用cocopod
的时候,会自动什么pod
的xcconfig
文件,如下:
其实这个xcconfig
文件类似于plist
文件,就是一个Key-Value的集合,其对应的就是Target
中的设置:
- 既然
cocopod
可以定义自己的xcconfig
文件,那么我们也可以定义自己的xcconfig
文件,这样做的好处是,将需要修改的环境变量集中到一个文件里面,这样便于管理。
下面我们自定义自己的xcconfig
文件:
- ⚠️ 注意:
xcconfig
文件的命名规则是:<文件夹名称-APP名称.对应的configuration>如下:
- 然后我们在
PROJECT
-Info
-Configurations
里面,将不同的configuration
设置对应的xcconfig
文件:
-
xcconfig
文件其实就是一个Key-Value
文件,对应的就是Target
的设置。下面我们来测试一下:
1、首先我们在Target
的Build Settings
里面设置自己的字段:
2、接着我们给工程加一个test1_Debug
的Scheme
,对应的就是Debug
模式;原来的test1
对应Release
模式:
3、根据上面讲的,将不同的configuration
设置对应的xcconfig
文件,在xcconfig
文件中我们这样写:
Debug
文件:APP_CONFIG = APP_Debug_Replace
Release
文件:APP_CONFIG = APP_Release_Replace
4、我们在Info.plist
文件中添加一个刚刚设置的字段:
5、打印我们自定义的字段:
NSString *path = [NSBundle.mainBundle pathForResource:@"Info" ofType:@"plist"];
NSDictionary *infoDic = [[NSDictionary alloc] initWithContentsOfFile:path];
NSLog(@"%@",infoDic[@"APP_CONFIG"]);
/*运行test1*/
输出结果:APP_Release_Replace
/*运行test1_Debug*/
输出结果:APP_Debug_Replace
讲到这里,大家可能会觉得第三种方法中,单独添加一个test1_Debug
完全就是多余,可以通过运行的时候切换test1
的configuration
也能实现上面的效果。
这里请大家考虑一下,实际的开发中,你面对的可能不只是Debug & Release
环境,可能有本地
、测试服
、正式服
等等。因此个人建议,用不同的Scheme
区分开,是比较高效的处理方式。
这里给大家推荐一个网站,可以查到Target
的各个字段对应的缩写:Xcode Build Settings
- 下面我们介绍一下最后一个知识点:xcconfig文件冲突
- 冲突 1:
实际开发中,我们会使用Cocopods
来管理我们的第三方库,Cocopods
也会给我们生成一些xcconfig
文件(这里注意⚠️ :每次pod
,Cocopods
都会从新生成xcconfig
文件,所以不要在Cocopods
生成的xcconfig
文件中做修改)
那么这个时候,就有一个问题,我们针对configuration
到底要选哪一个xcconfig
文件呢?
答案当然是我们自定义的xcconfig
这样有衍生出另一问题,那么pod
生成的xcconfig
我们该怎么处理,如果不添加,则pod install
就会出问题,如果是之前pod
好的工程,那么pod
中针对Target
的一些设置又该怎么办?
其实很简单,我们只需要在自定义xcconfig
文件中引入pod
生成的xcconfig
文件就可以了,如下:
#include "Pods/Target Support Files/Pods-test1/Pods-test1.debug.xcconfig"
- 冲突 2:
解决了上面的问题,我们来看另一问题,严格将问题2也是一个衍生问题。
如果自定义xcconfig
和 pod
生成的xcconfig
文件,对同一个字段进行了修改,那Xcode会用哪个文件中的配置呢?
答案是:自定义xcconfig
,其实大家想一下就明白了,自定义的 引用 pod
生成的,然后Xcode再引用自定义的。
那么像这种问题我们该怎么解决呢?
这里我们先给出答案:使用$(inherited)
,可以理解为继承。
下面我们看一下具体的使用场景:
首先我们在自定义的xcconfig
文件中添加
OTHER_LDFLAGS = -framework "SDWebImage"
同时我们也pod
了AFNetworking
。
此时我们会发现,在Target
的Build Settings
-Other Link Flags
路面只有SDWebImage
,如下:
这也就意味着,我们引入的第三方库的链接是失败的。
这时候,我们就可以在等号加上
-framework "SDWebImage"
:
OTHER_LDFLAGS = $(inherited) -framework "SDWebImage"
这里跟大家分享一下:问题 2 的解决办法,其实就在pod
自己生成的xcconfig
里面,如果有兴趣可以先不自定义xcconfig
,使用pod
引入一个三方库,看看pod
自动生成的xcconfig
是怎么写的,然后对应的Target
里面的设置又有了哪些变化。
Tips:
大家在配置自己的xcconfig
文件的时候有几个小技巧跟大家讲一下:
- 1、在
Build Settings
里面自定义了URL
字段,在xcconfig
如何配置//
的问题
如果我们直接在xcconfig
文件中写上对应的URL
会是被识别为注释符号
我们可以先定义一个/
的变量:
A = /
HOST_URL = ${A}/192.168.1.1
其中${A}
和 $(A)
是等价的。
- 2、比如说我们现在要配置
OTHER_LDFLAGS
,按照上面讲的我们是这样写的:
OTHER_LDFLAGS = -framework "SDWebImage"
其实我们还可以添加附加条件,比如:指定特定的开发环境、机型、架构等等,如下:
OTHER_LDFLAGS[config=Debug][sdk=iphonesimulator*][arch=x86_64] = -framework "SDWebImage"
此时OTHER_LDFLAGS
引入SDWebImage
只会在Debug
模式下,运行模拟器
并且对应的执行架构为x86_64
的时候,才会执行。
优先级(由高到低):
- 手动配置Target Build Settings
- Target中配置的xcconfig文件
- 手动配置Project Build Settings
- Project中配置的xcconfig文件