在 App 项目开发中会有多个编译环境的需求,给测试人员的测试环境,上线前的预发环境,以及上线后的正式环境。
此外,在接入第三方平台时,在不同环境下也需要使用不同的 Key。
在刚接触开发的时候,都是将这些信息写在代码里,把其它环境注释掉,需要的时候再手动的切换。
这样有一个很大的安全隐患,上线前有可能会忘记切换环境,导致将测试环境的 App 发布出去。
这时就需要用技术手段来规避这种低级错误。
多个 Target 方案
用 Xcode 新建工程,默认会创建 PROJECT 和 TARGETS,它们都有一个 Build Settings 选项。Project 的编译设置是默认的,而 Target 中的编译选项会对其进行覆盖。
因此我们可以通过创建多个 Target,并在 Preprocessor Macros 中配置宏,来创建多环境。
在代码中我们就可以这样写:
#if TEST
let host = "https://api.abc.com/test"
let appKey = abc...
#else
let host = "https://api.abc.com"
let appKey = def...
#endif
在不同的 Target 中也可以使用不同的 AppID,不同的 App icon 等。
在编译前切换 scheme 就会执行对应环境的代码。
这种切换方式将我们从修改代码中脱离出来,能够有效的避免低级错误。
.xcconfig 文件
这种方式是我们公司在使用的,在这之前都没想过有这种操作,灵感可能来源于 Xcode 默认存在 Debug 和 Release 两种编译环境。
这两个环境是通过 Xcode configurations 来实现的,因此我们可以自己添加一个配置。
然后创建一个配置文件 Congfig-Text.xcconfig:
将创建好的配置文件在 Project info 中关联:
现在我们开始编辑 .xcconfig 文件
// Config-Test.xcconfig
APP_SERVER_NAME = AppNameTest
APP_SERVER_HOST = https:\/\/api.abc.com/test
APP_PUSH_KEY = abc_test
// Config-Release.xcconfig
APP_SERVER_NAME = AppNameTest
APP_SERVER_HOST = https:\/\/api.abc.com/
APP_PUSH_KEY = abc_release
以上对应两种编译环境,不过这只是定义了值,如果是 OC 的代码,这些表达式就是宏定义,可以直接全局使用。
但如果是 Swift 代码,因为不支持宏定义,所以需要做一层处理,在开发中我们常常需要往 info.plist 文件中添加一些权限,可见系统在执行某些代码的时候会读取这个文件。
因此,我们也可以添加自定义的内容,并从中读取。
<key>AppServerHost</key>
<string>$(APP_SERVER_HOST)</string>
$() 中的变量是 .xcconfig 中定义的变量。
在代码中我们可以这样读取:
guard let infoDict = Bundle.main.infoDictionary,
let appHost = infoDict["AppServerHost"] else {
return
}
print(appHost)
在编译时选择编译环境,就会读取对应配置文件的值。
如果觉得切换比较深,可能新建一个 Scheme 并关联编译环境。
最后,在不同编译环境下用不同的 AppName 和 AppID 就更不可能混淆了。