背景: 应用开发总是会涉及到多个环境之间的切换,难道要打不同的域名包,还得给应用改个名字:开发包,测试包,正式包。 这样做,是否太浪费时间了,打包不需要时间吗?这种磨人的操作有没有一劳永逸的方法?
方法我倒是替你想到了,而且适用各种不同场景。如:
- 多环境之间的切换
- 有时候服务器需要他本地调试怎么办?手动输入不是问题
- 打包老是忘记关闭环境切换?那就只在debug模式才能切换,测试包你也是可以打debug包的。
配置域名也非常简单,只需要在 allHostArray 填上你需要切换的环境域名跟备注,在 mainHost 设置默认的域名
在你方便的地方触发下环境切换吧。对只需一句代码
DebugEnvManager.showDebugEnvView()
网络请求获取域名
DebugEnvManager.getHomeHost()
主代码:
class DebugEnvManager: NSObject {
static let mainHost = "https://xxx.com/"
/// 文件地址 视频,图片需要拼接的前缀 默认追加files/
// static let fileHost =
static let allHostArray = [
("外网", mainHost),
("测试", "https://xxx.test.com/"),
("你自己输入吧", "如:http://192.168.1.102:8080/"),
]
@objc class func getHomeHost() -> String {
#if DEBUG
if let host = UserDefaults.standard.object(forKey: "debug_env") as? String {
if host.contains("如:") {
if let selfHost = DebugEnvView.getCustomInputHost() {
return selfHost
}
return host.substingInRange(2..<host.count) ?? ""
}
return host
}else {
return mainHost
}
#endif
return mainHost
}
/// 获取自动去除端口的地址
class func getHomeHostNotPort() -> String {
var urlString = getHomeHost()
guard let url = URL(string: urlString), let port = url.port else {
return urlString
}
urlString = urlString.replacingOccurrences(of: ":\(port)", with: "")
return urlString
}
@objc static func getHomeHostShopApp() -> String {
return String.init(format: "\(self.getHomeHost())shop/")
}
@objc static func getHomeHostPath(_ path: String?) -> String {
guard var path = path else {
return self.getHomeHost()
}
if path.first == "/" {
path = path.substingInRange(1..<path.count) ?? ""
}
return String.init(format: "\(self.getHomeHost())\(path)")
}
/// 获取自动编码后的图片地址
@objc static func getImageURLPath(_ path: String?) -> String {
var urlString = autoHostImageURLPath(path)
if (URLComponents(string: urlString) == nil) {
urlString = urlString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? urlString
}
return urlString
}
/// 自动拼接有效图片地址
private static func autoHostImageURLPath(_ path: String?) -> String {
guard var urlString = path, !urlString.isEmpty else {
return ""
}
if urlString.first == "/" {
urlString = urlString.substingInRange(1..<urlString.count) ?? ""
}
if urlString.contains("http") {
return urlString
}else {
// 测试环境的图片拼接
var host = getHomeHost()
if host.contains("easydoc.xyz/mock") {
return String.init(format: "http://106.1.0.69:8080/\(urlString)")
}
// 自己输入的文件地址
if host == DebugEnvView.getCustomInputHost() {
if let fileHost = DebugEnvView.getCustomInputFileHost() {
return String.init(format: "\(fileHost)\(urlString)")
}
}
if !host.contains("9002") { // 文件地址统一添加 files
return String.init(format: "\(host)files/\(urlString)")
}
host = host.replacingOccurrences(of: "9002", with: "8080")
return String.init(format: "\(host)\(urlString)")
}
}
@objc class func showDebugEnvView() {
let view = DebugEnvView()
view.setup()
view.show()
}
// 是否是生成环境
class func isProduction() -> Bool {
if mainHost == DebugEnvManager.getHomeHost() {
return true
}
return false
}
}
UI视图代码
class DebugEnvView: UIView {
let kDebugWindowHeight = UIScreen.main.bounds.height
let kDebugWindowWidth = UIScreen.main.bounds.width
private var _tableView: UITableView!
func show() {
if UIApplication.shared.keyWindow?.subviews.contains(self) ?? false {
self.dimiss()
}
UIApplication.shared.keyWindow?.endEditing(true)
self.alpha = 0.0
UIApplication.shared.keyWindow?.addSubview(self)
UIView.animate(withDuration: 0.3) {
self.alpha = 1.0
}
}
@objc func dimiss() {
self.alpha = 1.0
UIView.animate(withDuration: 0.3, animations: {
self.alpha = 0.0
}) { (_) in
self.removeFromSuperview()
}
}
func setup() {
self.backgroundColor = UIColor.black.withAlphaComponent(0.3)
self.frame = UIScreen.main.bounds
self.addTapGesture()
let count = DebugEnvManager.allHostArray.count
let tableView = UITableView.init(frame: CGRect(x: 0, y: kDebugWindowHeight-CGFloat(count)*CGFloat(44.0), width: kDebugWindowWidth, height: CGFloat(count)*CGFloat(44.0)), style: .plain)
tableView.estimatedSectionHeaderHeight = 0;
tableView.estimatedSectionFooterHeight = 0;
tableView.delegate = self
tableView.dataSource = self
tableView.tableFooterView = UIView()
tableView.estimatedRowHeight = 0;
self.addSubview(tableView)
_tableView = tableView
}
}
extension DebugEnvView: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let count = DebugEnvManager.allHostArray.count
return count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "cell")
if cell == nil {
cell = UITableViewCell.init(style: .default, reuseIdentifier: "cell")
}
let hostName = DebugEnvManager.allHostArray[indexPath.row]
let homeHost = DebugEnvManager.getHomeHost()
cell?.separatorInset = UIEdgeInsets.zero
cell?.layoutMargins = UIEdgeInsets.zero
cell?.textLabel?.text = hostName.0
cell?.textLabel?.font = UIFont.systemFont(ofSize: 14)
cell?.textLabel?.textColor = UIColor.gray
cell?.textLabel?.textAlignment = .center
if hostName.1 == homeHost {
cell?.textLabel?.textColor = UIColor.red
}
// 自己输入的
if let selfHost = DebugEnvView.getCustomInputHost() {
if homeHost == selfHost && hostName.1.contains("如:") {
cell?.textLabel?.textColor = UIColor.red
var allString = selfHost
if let host = DebugEnvView.getCustomInputFileHost() {
allString = "\(allString)$$\(host)"
}
cell?.textLabel?.text = "输入地址:\(allString)"
}
}
return cell!
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
self.dimiss()
if customInputHost(DebugEnvManager.allHostArray[indexPath.row]) {
return;
}
UserDefaults.standard.set(DebugEnvManager.allHostArray[indexPath.row].1, forKey: "debug_env")
UserDefaults.standard.synchronize()
}
// 可以自己输入域名
func customInputHost(_ host: (name: String,ip: String)) -> Bool {
if host.0.contains("你自己输入吧") {
// 文件地址用$$拼接在后面
let alert = UIAlertController.init(title: "输入请求地址,记得+http://$$文件地址", message: nil, preferredStyle: .alert)
alert.addTextField(configurationHandler: { (textF) in
textF.placeholder = host.1
var allString = ""
if let host = DebugEnvView.getCustomInputHost() {
allString = host
}
if let host = DebugEnvView.getCustomInputFileHost() {
allString = "\(allString)$$\(host)"
}
textF.text = allString
})
alert.addAction(UIAlertAction.init(title: "确认", style: .default, handler: { (_) in
guard let text = alert.textFields?[0].text else {
EPHud.showInfo("不想输入算了")
return;
}
if text.contains("http://") || text.contains("https://") {
let urls = text.components(separatedBy: "$$")
UserDefaults.standard.set(host.1, forKey: "debug_env")
UserDefaults.standard.set(urls[0], forKey: "debug_env_self_input")
if urls.count > 1 { // 获取文件地址
UserDefaults.standard.set(urls[1], forKey: "debug_env_self_input_file")
}
UserDefaults.standard.synchronize()
self.dimiss()
}else {
EPHud.showInfo("记得添加http://前缀")
}
}))
EPCtrlManager.getTopVC()?.present(alert, animated: true, completion: nil)
return true;
}
return false
}
// 获取自己输入的请求域名
static func getCustomInputHost() -> String? {
if let selfHost = UserDefaults.standard.object(forKey: "debug_env_self_input") as? String {
// 末尾自动追加 "/"
if selfHost.last == "/" {
return selfHost
}else {
return "\(selfHost)/"
}
}
return nil
}
// 获取自己输入的文件域名
static func getCustomInputFileHost() -> String? {
if let selfHost = UserDefaults.standard.object(forKey: "debug_env_self_input_file") as? String {
// 末尾自动追加 "/"
if selfHost.last == "/" {
return selfHost
}else {
return "\(selfHost)/"
}
}
return nil
}
}
extension DebugEnvView: UIGestureRecognizerDelegate {
func addTapGesture() {
let tapGes = UITapGestureRecognizer.init(target: self, action: #selector(dimiss))
tapGes.delegate = self
self.addGestureRecognizer(tapGes)
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
let point = touch.location(in: self)
return !_tableView.frame.contains(point)
}
}