我一直在做的可能是一种比检查代码中的常量并在每个环境中到处乱扔同一变量的不同值更灵活的方法。
也不需要创建 .xcconfig 文件。
设置整个东西需要更多的工作,但之后您会发现它非常容易使用。
在我的示例中,您会看到我如何在 Toeppersee iOS app 中为生产/UITest/开发构建设置不同的 REST 端点。
更改您的Info.plist
首先,只需定义一个新常量并选择一个标识您的内容的名称,在我的例子中是TS_WEBSERVICE_URL:
确保将其值设置为您选择的名称,用 $() 括起来(括号,而不是大括号!),在我的例子中是 $(TS_WEBSERVICE_URL)。
构建设置
在您的构建设置选项卡中,添加自定义的“用户定义”构建参数,再次使用相同的名称:
您看到您可以为 Debug、UITests 和 Release 定义值。而且我将这种机制用于环境中不同的很多事情。
添加更多环境
如果您需要更多环境,请将它们添加到您的主项目节点的信息选项卡中(就像我在这里使用 UITests 所做的那样):
使用代码中的值
现在来说最简单的部分:在代码中使用新定义的值。这一切都归结为获取一个 NSBundle 实例并读取在您的 Info.plist 中定义的值,该值已在构建过程中自动替换。
目标 C:
NSString *webserviceURL = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"TS_WEBSERVICE_URL"];
斯威夫特:
let webserviceURL = Bundle.main.object(forInfoDictionaryKey: "TS_WEBSERVICE_URL") as! String
每个环境设置只需一行代码。
有一件事我没有展示,但也相当简单:只需为NSBundle 定义一个类别并提供名为webserviceUrl 的新方法和类似方法。然后可以像这样调用它们:Bundle.main.webserviceUrl(),这更加简化了源代码。
编辑:将扩展写入 Bundle 对象(可选)
为了实现上述对 Web 服务 URL 的简化访问,创建并调用了一个新的 Swift 文件(例如):Bundle+AppAdditions.swift
import Foundation
// An extension (or category in Objective C) extends any types functionality,
// in our case the NSBundle foundation class.
extension Bundle {
// get the webservice URL from an NSBundle instance
public func webserviceUrl() -> String {
// get an object for info dictionary key and cast it as string
return self.object(forInfoDictionaryKey: "TS_WEBSERVICE_URL") as! String
}
}
该扩展直接适用于任何给定的Bundle 实例,不一定只适用于main 包。示例:
let url = Bundle.main.webserviceUrl()
或任何其他捆绑包,例如对于包含 InitialViewController 的 App Clip Extension:
let url = Bundle(for: InitialViewController.self).webserviceUrl()
我实际上会添加另一个静态扩展方法来获取应用剪辑扩展包。但这也是可选的;-)