Step 9. Collect the username and password
To handle the Callback objects
-
Implement the UI controls that collect the username and password. For each callback that is received, display a UIAlertController to collect the required information. In this case we require only the
nameCallback
and thepasswordCallback
.For demonstration purposes, this example uses a simple
UIAlertController
to collect the username and password, rather than implementing a custom UI login screen:else if let node = node { print("Node object received, handle the node") DispatchQueue.main.async { let alert = UIAlertController(title: "User Authentication", message: nil, preferredStyle: .alert) for callback: Callback in node.callbacks { if callback.type == "NameCallback", let nameCallback = callback as? NameCallback { alert.addTextField { (textField) in textField.placeholder = nameCallback.prompt textField.autocorrectionType = .no textField.autocapitalizationType = .none } } else if callback.type == "PasswordCallback", let passwordCallback = callback as? PasswordCallback { alert.addTextField { (textField) in textField.placeholder = passwordCallback.prompt textField.autocorrectionType = .no textField.autocapitalizationType = .none } } } let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil) let submitAction = UIAlertAction(title: "Next", style: .default) { (_) in var index = 0 for textField in alert.textFields! { let thisCallback: SingleValueCallback = node.callbacks[index] as! SingleValueCallback thisCallback.setValue(textField.text) index += 1 } node.next { (user: FRUser?, node, error) in self.handleNode(user: user, node: node, error: error) } } alert.addAction(cancelAction) alert.addAction(submitAction) self.present(alert, animated: true, completion: nil) } }
-
Run the application.
-
When you click the Login button, the UI alert displays the text fields for collecting the username and password:
-
To submit the content of the text fields to the SDK, click the Next button.
The SDK sends the information to the server:
-
The
submitAction
retrieves the callback from the node to ensure that the values in the text fields can be input into the callback.Note that this code uses a
SingleValueCallback
, because both theNameCallback
and thePasswordCallback
inherit from theSingleValueCallback
. -
In the callback, set the value of the callback to the value of the text field.
-
Increment the value to iterate through the text fields.
-
Move to the next node, and pass the process to the
handleNode()
method.
Your complete
ViewController.swift
should now resemble the following:// // ViewController.swift // DemoApp // import UIKit import FRAuth class ViewController: UIViewController { @IBOutlet weak var statusLabel: UILabel? @IBOutlet weak var loginButton: UIButton? override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. FRLog.setLogLevel([.error, .network]) do { try FRAuth.start() print ("SDK initialized successfully") } catch { print (error) } updateStatus() } func updateStatus() { if let _ = FRUser.currentUser { statusLabel?.text = "User is authenticated" } else { statusLabel?.text = "User is not authenticated" } } func handleNode(user: FRUser?, node: Node?, error: Error?) { if let _ = user { print("User is authenticated") DispatchQueue.main.async { self.updateStatus() } } else if let node = node { print("Node object received, handle the node") DispatchQueue.main.async { let alert = UIAlertController(title: "User Authentication", message: nil, preferredStyle: .alert) for callback: Callback in node.callbacks { if callback.type == "NameCallback", let nameCallback = callback as? NameCallback { alert.addTextField { (textField) in textField.placeholder = nameCallback.prompt textField.autocorrectionType = .no textField.autocapitalizationType = .none } } else if callback.type == "PasswordCallback", let passwordCallback = callback as? PasswordCallback { alert.addTextField { (textField) in textField.placeholder = passwordCallback.prompt textField.autocorrectionType = .no textField.autocapitalizationType = .none } } } let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil) let submitAction = UIAlertAction(title: "Next", style: .default) { (_) in var index = 0 for textField in alert.textFields! { let thisCallback: SingleValueCallback = node.callbacks[index] as! SingleValueCallback thisCallback.setValue(textField.text) index += 1 } node.next { (user: FRUser?, node, error) in self.handleNode(user: user, node: node, error: error) } } alert.addAction(cancelAction) alert.addAction(submitAction) self.present(alert, animated: true, completion: nil) } } else { print ("Something went wrong: \(String(describing: error))") } } @IBAction func loginButtonPressed(sender: UIButton) { print("Login button is pressed") FRUser.login {(user: FRUser?, node, error) in self.handleNode(user: user, node: node, error: error) } } }
-