Server Switching
This demo app supports multiple servers. To switch servers, you normally need to update the server configuration files and restart the app for the changes to take effect. By adding the code below, you can automate this process to change the server and exit the app automatically.
To change your current server within the app, follow these steps:
- Open the app and select
Select Server
- Now you can select server from a list
In ChangeServerVC class you can see the code that we have added for server switching. Inside tableview delegate method didSelectRowAt.
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
MultiAssets.current = MultiAssets.assets[indexPath.row]
tableView.reloadData()
let actionResult = ActionResult(title: "Select Server", success: true, error: nil, duration: 0, event: nil)
appCoordinator.actionResult(actionResult: actionResult)
}
Now we have two restart events, one is the "normal" restart that you are using for logout purpose, but here, we use a restart event with all the parameters that are passed in the StartEvent. So now you do not have to forcefully close the application and restart the application to use changed environment in your application.
Notes:
After switching the environment from x to y and if you have some user in your application registered in the x environment and in the y environment you will get the user of x also in start/restart event result and if you want to perform login with the user from x environment then you will get a Runtime error or sometimes this user is deleted by MC itself. But if you receive RuntimeError and you are not able to perform a login or to add a user then first delete the user of the x environment and then continue with activation in the y environment.
func restartMaster(traceParent: String? = nil, assetBundle: AssetBundle? = nil, completion: @escaping (ActionResult) -> Void) {
let startHelper = StartHelper(assetBundle: assetBundle)
let restart = KSMRestartEventEx(serverBackend: (GlobalConstats.mcConfig?.astServerBackend)!,
ssmsAppConfiguration: startHelper.appConfig,
mcConfig: startHelper.mcConfigString,
certificateChain: startHelper.certData)
if let traceParent {
let state = restart.traceContext.traceState
restart.traceContext = .init(traceParent: traceParent, traceState: state)
}
let time = CallTimer(event: restart)
MasterControllerAdapter.sharedInstance.sendEvent2MasterController(event: restart) { event in
let duration = time.stop()
if let result = event as? KSMRestartResultEvent {
if result.status == .KSMOK {
completion(ActionResult(title: "Restart",
success: true,
error: nil,
duration: duration,
event: result))
} else {
print("Start failed")
completion(ActionResult(title: "Restart",
success: false,
error: "Failed with Status \(result.status)",
duration: duration,
event: result))
}
}
}
// OtelTraceHandler.shared.complete(traceName: "RestartEventSpan")
}
Here we can save the current server assets path in UserDefaults or you can save this information in keychain or any local DB.
static var current: AssetBundle {
get {
var isDir = ObjCBool(true)
if let savedAssets = UserDefaults.standard.object(forKey: assetKey) as? Data {
let decoder = JSONDecoder()
if let assetBundle = try? decoder.decode(AssetBundle.self, from: savedAssets) {
if assetBundle.locationName == "App" {
let path = appAssetsURL.appendingPathComponent(assetBundle.name).path
if FileManager.default.fileExists(atPath: path, isDirectory: &isDir) {
return assetBundle
}
} else if assetBundle.locationName == "Documents" {
let path = documentsAssetsUrl.appendingPathComponent(assetBundle.name).path
if FileManager.default.fileExists(atPath: path, isDirectory: &isDir) {
return assetBundle
}
}
}
}
// Default value
let assetBundle = AssetBundle(name: defaultServer, locationName: "App")
return assetBundle
}
set {
let encoder = JSONEncoder()
if let encoded = try? encoder.encode(newValue) {
UserDefaults.standard.set(encoded, forKey: assetKey)
}
}
}
Flow Chart For Receiving Events:
The below image shows receiving an event from the master controller and forwarding it to the registered view controller