iOS 基础xcodeiOS技术交流

Configurations + xcconfig配置多环境

2017-06-30  本文已影响227人  Randy1993

前言

一个APP的开发涉及到多种环境在所难免,比如Test环境,UAT(User Acceptance Test)用户验收测试环境,Release环境等等。我的项目需求是,在不同的环境下在代码中使用到了变量值不一样,比如说请求的接口。这里作一个记录和分享。

Configuration配置

配置Configuration的目的是为了增加或删除编译环境,对于不同编译环境下的参数需求可以到xcconfig中进行设置。

1、进入工程的info页,下面红框中标明的是工程创建时自带的两个编译环境Debug和Release。

1.png

点击下面的加号添加新的编译环境,根据需要选择Duplicate Debug和Duplicate Release,他们的区别在于,后者会进行各种优化,包括编译的优化,导致不能调试(不能通过断点、LLDB查看变量),另外Release环境下打的包也会更轻量一些。这里我将Debug环境名改为UAT_α,并增加一个基于Debug 的UAT_β环境。


2.png

插曲:如果想要在Relase环境下去调试可以前往Bulid Setting总进行设置,将Release下的参数换成和Debug一样即可:


3.png

2、配置预编译宏,这就相当于在pch文件当中去定义宏,可以在项目中做不同环境的区分,进而进行操作。进入工程的Build Setting ->Preprocessor Macros:


Snip20170629_10.png

我们看到UAT_α和UAT_β对应的值均为DEBUG = 1,我们可以理解的是在两种环境下同时定义了#define DEBUG 1,为了表示区别可以分别设置为不同的宏名和值,例如:ConfigDemo_ UAT_α=0,ConfigDemo_ UAT_β=1(等号两边不能留空格,否则会编译出错)。GCC提供了一种动态编译的方法:ConfigDemo_${CONFIGURATION}=0, ConfigDemo_${CONFIGURATION}=1,这两种设置方法是等价的(注意不要动$(inherited),他表示继承工程的默认设置)。

3、进行Scheme的配置,可以理解一个Scheme对应一个Target、一种环境(当然这里只有一个Target,只是编译环境不同)。 当我们切换不同的Scheme运行时就是切换不同的环境了。在Xcode的左上角选择添加新的Scheme,并分别添加ConfigDemo_ UAT_α,ConfigDemo_ UAT_β两个Scheme:


Snip20170629_11.png Snip20170629_13.png

添加完Scheme后对其进行配置,我们刚才配置环境后总共有Release、UAT_α、UAT_β三种环境,在这里使他们分别对应ConfigDemo、ConfigDemo_ UAT_α,ConfigDemo_ UAT_β,选择Edit Scheme,这里可以将Run、Test、Archive改为对应的Scheme,关于他们的解释

Snip20170629_15.png

于是在代码中就可以进行如下操作:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
#ifdef ConfigDemo_UAT_α
    
#define TestString @"ConfigDemo_UAT_α"
    
#elif ConfigDemo_UAT_β
    
#define TestString @"ConfigDemo_UAT_β"
    
#else //Release
    
#define TestString @"Release"
    
#endif
    
    NSLog(@"TestString:%@",TestString);
    
    // 打印结果分别为Release、ConfigDemo_UAT_α、ConfigDemo_UAT_β
}

根据不同的Scheme配置不同的displayName、APPICON等可以参见文章最后的链接;

配置xcconfig

关于项目的参数需要做一下说明:

xcconfig文件的修改实际上是修改build setting中的参数。Projects 会包含一个或者多个 targets,这里可以理解每一种编译环境对应一个target,每一个 target 将会产出一个 product.这些指令以 build setting 和 build phases 的形式存在,你可在 Xcode 的项目编辑器(TARGETS->Build Setting, TARGETS->Build Phases)中进行查看和编辑。target 中的 build setting 参数继承自 project 的 build settings, 但是你可以在 target 中修改任意 settings 来重写 project settings,这样,最终生效的 settings 参数以在 target 中设置的为准. Project 可包含多个 target, 但是在同一时刻,只会有一个 target 生效,可用 Xcode 的 scheme 来指定是哪一个 target 生效,虽然这里并没有配置多个Target,但是这里还是可以理解一个Scheme对应一个Target。
另外要说明一点,对于项目中其他地方的配置,可以直接在操作板中复制粘贴到文件中来进行修改,最终xcconfig的设置会覆盖原来的设置。

对于需要单独配置参数的环境则生成一个xcconfig文件,没有单独配置xcconfig的则使用默认的设置,另外在这里需要生成一个公用的xcconfig文件。
Snip20170629_8.png Snip20170629_9.png
每个文件代码的写法:
  1. Common. xcconfig的写法
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) VariableA='$(VariableA)' VariableB='$(VariableB)'

解析如下:
其作用是将配置文件中定义的常量定义成预编译宏,以便于在代码中获取。
GCC_PREPROCESSOR_DEFINITIONS 是 GCC 预编译头参数,对应的设置在 Xcode8下的路径为 Build Settings->Apple LLVM 7.x Preprocessing->Preprocessor Macros,就是我上面提到的设置预编译宏,这里权且可以理解上面这一串代码是在Build Setting中设置预编译宏的代码化,而这里的设置并不会覆盖之前在Build Setting中的设置,只会将这些新增的设置添加到最后面。 上面代码的意思是,定义两个预编译的宏名字分别为VariableA、VariableB,他们具体的值就可以在不同的xcconfig中去设置,不同的xcconfig需要导入这一个Common. xcconfig的文件,这就实现了不同环境下动态的配置,不同环境下的预编译宏名一样只是值会不一样,而且这些xcconfig文件可以在不同的项目中使用。
这样就可以简单的理解为Common. xcconfig实现了一个Build Setting里面的一个方法,而其他的xcconfig文件调用这个方法进行具体设置。
上面在Preprocessor Macros中配置的用于在代码中区分不同环境的预编译宏,也可以直接在Common. xcconfig中设置,只是在代码中进行区分就要区分不同宏的值了。

2.其他xcconfig代码:

#include "Common.xcconfig"

VariableA = @"UAT_α.xcconfig_VariableA"
VariableB = @"UAT_α.xcconfig_VariableB"

3、将xcconfig与环境进行关联:
我们来到工程下的info->Configuration,


Snip20170630_19.png

我们发现,每一种环境下都有两个这样的设置,一个设置是工程的xcconfig文件配置,另一个则是target的xcconfig文件配置,在这里配置xcconfig意味着APP在运行的时候会去加载相应xcconfig中的设置。上面我们说到了配置的继承关系,那么这里只设置target的xcconfig就够了,而且你设置了工程的xcconfig就相当于在编译的时候将这些xcconfig的配置加载设置了两遍!其实你也会发现此时再设置工程的xcconfig也没有关系。这里我暂且只设置UAT_α和UAT_β环境下的xcconfig,Release环境留着调式pod。

Snip20170630_20.png

接下来你就可以直接在代码中使用VariableA、VariableB宏了:

// 这里并不能在Release环境下使用这些宏,否则会报错。
   NSLog(@"%@ - %@",VariableA, VariableB);
    // ConfigDemo_UAT_α、ConfigDemo_UAT_β环境打印结果分别为
    // UAT_α.xcconfig_VariableA - UAT_α.xcconfig_VariableB
    // UAT_β.xcconfig_VariableA - UAT_β.xcconfig_VariableB

Pod调试,Pod安装SDWebImage

在删除上面的log代码之后,你会发现只有在Release环境下能够运行!首先我们来看看报错:

Snip20170630_22.png

是的,工程找不到相关文件了,其实这个你在终端的提示中就可以发现端倪:

Snip20170630_21.png

大概意思是你需要你配置的xcconfig文件中导入pod配置文件的路径。

在完成一次pod install之后,Pods工程会为每一个环境生成一个xcconfig文件,包括默认的debug环境,如果我们的目标工程ConfigDemo对应的环境没有配置xcconfig文件,那么就会在ConfigDemo工程下拷贝一份对应的xcconfig文件并自动在环境中完成配置,这种配置让工程能够使用pod。大家可以看到这里在ConfigDemo工程下只有Release. xcconfig文件的拷贝,而此时Release环境下的Configuration配置已经发生了改变。

Snip20170630_24.png Snip20170630_25.png

我们只需要在其他xcconfig文件中导入相关的pod下的xcconfig就好了,记得使用相对路径,否则在其他电脑上就不能运行了:

#include "Pods/Target Support Files/Pods-ConfigDemo/Pods-ConfigDemo.release.xcconfig"

这个时候你就可以删除在ConfigDemo工程下的.release.xcconfig文件,并去Configuration中配置你自己的xcconfig文件了,记得重新pod install一下。

Demo:https://github.com/Randy1993/ConfigDemo

参考文章:

http://www.jianshu.com/p/83b6e781eb51
http://liumh.com/2016/05/22/use-xcconfig-config-specific-variable/#xcconfig-environment 关于xcconfig文件的说明。
http://www.jianshu.com/p/51a2bbe877aa Configuration配置

Stay hungry,Stay foolish!

上一篇下一篇

猜你喜欢

热点阅读