iOS之深入解析多环境配置的实现方案

Posted Forever_wj

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS之深入解析多环境配置的实现方案相关的知识,希望对你有一定的参考价值。

一、多 target 形式配置多环境

  • 如下所示,选择工程 TARGETS,新创建一个 targets:

  • 创建完成后,可要发现产生了一个 plist 文件,这个 plist 就是对应新创建的 target:

  • 修改 target 名为 LoginApp-Dev,target 是一个全新生成的,因此需要修改 bundle ID,设置为 com.ydw.LoginApp-Dev,同时它也有一个自己的 plist 配置文件,也就是上面一起生成的,也修改为 LoginApp-Dev-info.plist,如下所示:

  • Build Setting 中的 plist 如下:

  • 为新的 target 添加新的 AppIcon,如下所示,创建一个 AppIcon:

  • 再到 Build Setting 里将 icon 重新设置一下,这样两个 target 就可以展示不同的 icon:

  • 编译运行,可以发现两个 target 会生成两个 App:

  • 平时如果需要在 dev 和 release 环境下执行不同的代码,一般是需要定义宏来进行区分,而项目默认有个宏 DEBUG,其实是在下面自定义的:

  • 可以自定义一个 dev 在 debug 环境下等于 1,在 release 环境下等于 0,如下所示:

  • 测试可以发现在 release 和 debug 模式下运行,可以看到打印的结果是不一样的,说明我们定义的宏起作用了。
  • 在 Swift 模式下,需要特定的设置方式,可以在 other Flags 里面创建一下变量在 Swift 代码下使用,但是要在定义的变量前面加个 -D:

  • 这样,在 Swift 类里面便可以使用:

  • 假如项目有多环境,而 debug 和 release 两个环境不足以使用,那只需要在不同的 target 下将宏定义成不同的值,即可更换不同的环境。可以看到这种方法比较繁琐,每个环境都有不同 plist 文件,还需要在每个 target 下进行配置等,配置麻烦。

二、多 scheme 方式配置多环境

① 概念说明
  • Project:包含了项目所有的代码,资源文件,所有信息;
  • Target:指定代码和资源文件的具体构建方式;
  • Scheme:指定 target 的环境配置。
② 添加 Config
  • 运用多 target 形式配置多环境,可以看到不同的环境可以在不同 Config 下进行配置,target 下只有 debug 和 release,如果可以需要多种配置,就不必使用多个 target 配置了,我们可以给 Project 添加几个 Config,如下所示:

  • 现在添加一个叫 Beta 的 Config:

  • 然后到 Edit scheme 里面,可以看到 build Configuration 变成了三种模式:

  • 并且 target 下所涉及到的配置地方也都变成三种模式:

③ 添加 scheme
  • 利用多 scheme 方式,每次都需要在 Edit scheme 里面修改 scheme 对应的配置环境也显得比较麻烦。不过可以在 manager scheme 里面进行添加 Scheme,这样就能在同一个 target 下,直接切换不同的 scheme 来进行环境的切换:

  • 再看一下项目的 scheme,可以发现能直接进行切换:

④ 将不同的 scheme 配置对应的 config
  • 为了将不同的 scheme 配置对应的 configuration,可以在 Edit Scheme 里面进行配置,如下所示,将不同的 scheme 配置不同的 configuration 即可:

⑤ 在 user-Defined中 添加需要的变量
  • 在 Buidle Settiongs 里面添加一个自定义的 User-Defined:

  • 可以看到自定义的 User-Defined 里面也区分了三种 configuration,因此可以在不同配置下定义不同的值,如下所示,配置不同环境的 URL 地址:

⑥ 通过 info.plist 将定义的变量公开出去
  • 由于直接通过代码无法获取配置的值,但是可以通过代码获取 plist 文件的设置,因此可以在 plist 里面将配置的变量公开出去,然后在代码中读取 plist 的内容:

  • 如下所示,可以发现在不同的配置下读取的值是不同的:

  • 运用这种方式,可以通过这种方式让代码在一种环境下运行,在一种环境下不运行,同时也可以在可以配置的地方配置不同环境下的内容。比如“图标配置”如下:

三、运用 config 配置文件配置多环境

① Cocoapods 创建的配置文件
  • 使用过 Cocoapods 的都知道,工程中会产生如下的配置文件:

  • 进入到 project 的 configuration 也可以看到:

  • 这些都是 Cocoapods 创建的,那么手动来创建一个配置文件是否能生效呢?
② 创建 config 配置文件
  • 创建 config 配置文件入口如下:

  • 创建两个 config 文件,文件名命名需要遵守如下形式:文件名 + 工程名 + 环境名:

③ 将 config 文件配置到对应的 configuration 中
  • 将 config 文件配置到对应的环境中:

  • 也看到 Target 也可以选择配置文件,因为在 Target 的 BuildSetting 里面也有相应环境的配置,也可以通过 config 文件进行配置。
④ 在 config 文件中定义相应的变量
  • 在三个 config 文件中分别创建一个变量 URL_HOST,如下:

  • 在 plist 里面将配置文件的变量公开出去:

  • 再用代码读取:
	NSString *path = [NSBundle.mainBundle pathForResource:@"Info" ofType:@"plist"];
    NSDictionary *infoDic = [[NSDictionary alloc] initWithContentsOfFile:path];
    NSLog(@"%@",infoDic[@"URL_HOST"]);
  • 这样就可以实现,在 Dev、Release、Beta 三种环境下,分别读取对应的 URL_HOST 的值。
  • 这样一来,通过 config 配置文件进行配置比 scheme 方便很多,因此可以将多 config 配合多个 scheme 一起使用,这样会更加灵活和简便。并且,配置文件可以配置更多的内容,包括 buildSetting 里面所有涉及到环境的选项,例如 Other Linker Flags,可以在 config 配置上 OTHER_LDFLAGS。

  • 编译一下,便可以在 buildsetting 里看到 Other Linker Flags 中:Beta 里面配置上了 framework。

  • 其实 OTHER_LDFLAGS 就是配置到链接器里面,本质上 Config 文件是 key-value 形式进行配置的,既然 OTHER_LDFLAGS 可以配置,那 Build Setting 里面所有涉及到环境变量的参数都能配置,还有很多参数都可以配置,具体可以参考:
  • 综上,我们可以通过 config 文件对 Build Setting 进行配置,也就是可以将配置从 buildSetting 分离出来,然后通过环境的不同进行配置。
  • 如果项目中有多个 config 文件应该怎么处理呢?config 和本身 Build Setting 里面的配置会不会产生冲突呢?在项目中使用 Cocoapods,然后 pod install 时候会发现 Cocoapods 会提示如下警告:
	[!] CocoaPods did not set the base configuration of your project because your project already has a custom config set. In order for CocoaPods integration to work at all, please either set the base configurations of the target `LoginApp` to `Target Support Files/Pods-LoginApp/Pods-LoginApp.debug.xcconfig` or include the `Target Support Files/Pods-LoginApp/Pods-LoginApp.debug.xcconfig` in your build configuration (`LoginApp/Config/LoginApp.Dev.xcconfig`).
	
	[!] CocoaPods did not set the base configuration of your project because your project already has a custom config set. In order for CocoaPods integration to work at all, please either set the base configurations of the target `LoginApp` to `Target Support Files/Pods-LoginApp/Pods-LoginApp.beta.xcconfig` or include the `Target Support Files/Pods-LoginApp/Pods-LoginApp.beta.xcconfig` in your build configuration (`LoginApp/Config/LoginApp.Beta.xcconfig`).
	
	[!] CocoaPods did not set the base configuration of your project because your project already has a custom config set. In order for CocoaPods integration to work at all, please either set the base configurations of the target `LoginApp` to `Target Support Files/Pods-LoginApp/Pods-LoginApp.release.xcconfig` or include the `Target Support Files/Pods-LoginApp/Pods-LoginApp.release.xcconfig` in your build configuration (`LoginApp/Config/LoginApp.Release.xcconfig`).
  • 这个警告就是 Cocoapods 检测到了工程手动配置了 config 文件,但是它没有自动兼容配置,需要我们将 Cocoapods 生成的 config 文件导入到自定义的 config 文件里。例如,在 beta 配置文件中,通过 include + 文件路径导入,导入 pod 的配置文件之后在进行 pod install,可以发现警告消除了,如下:
	#include "Pods/Target Support Files/Pods-LoginApp/Pods-LoginApp.beta.xcconfig"
  • 这样一来,Cocoapods 对应的配置文件便可以引入成功,但是如果手动的配置文件和 Cocoapods 的配置文件里都有相同的配置内容,那么哪个会生效呢?如下,Cocoapods 的配置文件和手动配置文件都有 AFNetworking 三方库的配置:

  • 可以看到,在 Cocoapods 配置文件中有一个关键字: $(inherited) 可以理解为“继承”的意思,它会将导入的 Config 文件里相同变量的值拼接起来,但是在 Build Setting 里面只会显示 inherited 里面本身所配置的,还有配置的 Config 文件里面的信息,但是实际上所有的信息都是导入的。因此在对应的 Config-LoginApp.Beta.xcconfig 文件中,修改如下:
	OTHER_LDFLAGS = $(inherited) -framework "AFNetworking"
  • 然后在 Build Setting 便可以看到配置成功,工程中便可以正常使用这个三方库了。如下所示:

以上是关于iOS之深入解析多环境配置的实现方案的主要内容,如果未能解决你的问题,请参考以下文章

iOS之深入解析CFRunloop的多线程隐患

iOS之深入解析编译过程的原理与应用

iOS之深入解析静态库和动态库

iOS之深入解析类加载的底层原理:类如何加载到内存中?

数据结构与算法之深入解析“分割数组的最多方案数”的求解思路与算法示例

数据结构与算法之深入解析“分割数组的最多方案数”的求解思路与算法示例