Any user using the SUSI iOS client can set preferences like enabling or disabling the hot word recognition or enabling input from the microphone. These settings need to be stored, in order to be used across all platforms such as web, Android or iOS. Now, in order to store these settings and maintain a synchronization between all the clients, we make use of the SUSI server. The server provides an endpoint to retrieve these settings when the user logs in.
First, we will focus on storing settings on the server followed by retrieving settings from the server. The endpoint to store settings is as follows:
http://api.susi.ai/aaa/changeUserSettings.json?key=key&value=value&access_token=ACCESS_TOKEN
This takes the key value pair for storing a settings and an access token to identify the user as parameters in the GET request. Let’s start by creating the method that takes input the params, calls the API to store settings and returns a status specifying if the executed successfully or not.
let url = getApiUrl(UserDefaults.standard.object(forKey: ControllerConstants.UserDefaultsKeys.ipAddress) as! String, Methods.UserSettings) _ = makeRequest(url, .get, [:], parameters: params, completion: { (results, message) in if let _ = message { completion(false, ResponseMessages.ServerError) } else if let results = results { guard let response = results as? [String : AnyObject] else { completion(false, ResponseMessages.ServerError) return } if let accepted = response[ControllerConstants.accepted] as? Bool, let message = response[Client.UserKeys.Message] as? String { if accepted { completion(true, message) return } completion(false, message) return } } })
Let’s understand this function line by line. First we generate the URL by supplying the server address and the method. Then, we pass the URL and the params in the `makeRequest` method which has a completion handler returning a results object and an error object. Inside the completion handler, check for any error, if it exists mark the request completed with an error else check for the results object to be a dictionary and a key `accepted`, if this key is `true` our request executed successfully and we mark the request to be executed successfully and finally return the method. After making this method, it needs to be called in the view controller, we do so by the following code.
Client.sharedInstance.changeUserSettings(params) { (_, message) in DispatchQueue.global().async { self.view.makeToast(message) } }
The code above takes input params containing the user token and key-value pair for the setting that needs to be stored. This request runs on a background thread and displays a toast message with the result of the request.
Now that the settings have been stored on the server, we need to retrieve these settings every time the user logs in the app. Below is the endpoint for the same:
http://api.susi.ai/aaa/listUserSettings.json?access_token=ACCESS_TOKEN
This endpoint accepts the user token which is generated when the user logs in which is used to uniquely identify the user and his/her settings are returned. Let’s create the method that would call this endpoint and parse and save the settings data in the iOS app’s User Defaults.
if let _ = message { completion(false, ResponseMessages.ServerError) } else if let results = results { guard let response = results as? [String : AnyObject] else { completion(false, ResponseMessages.ServerError) return } guard let settings = response[ControllerConstants.Settings.settings.lowercased()] as? [String:String] else { completion(false, ResponseMessages.ServerError) return } for (key, value) in settings { if value.toBool() != nil { UserDefaults.standard.set(value.toBool()!, forKey: key) } else { UserDefaults.standard.set(value, forKey: key) } } completion(true, response[Client.UserKeys.Message] as? String ?? "error") }
Here, the creation of the URL is same as we created above the only difference being the method passed. We parse the settings key value into a dictionary followed by a loop which loop’s through all the keys and stores the value in the User Defaults for that key. We simply call this method just after user log in as follows:
Client.sharedInstance.fetchUserSettings(params as [String : AnyObject]) { (success, message) in DispatchQueue.global().async { print("User settings fetch status: \(success) : \(message)") } }
That’s all for this tutorial where we learned how to store and retrieve settings on the SUSI Server.
References
- User Defaults: Apple’s docs listing various methods for using User defaults
- Ray Wenderlich Tutorial: Tutorial on how to use User Defaults
- GCD and Dispatch Queues in Swift Tutorial: Tutorial highlighting the usage of threads in swift
- Video Tutorial from WWDC 2016: Video tutorial on concurrent programming from WWDC 2016