Create a UI in Swift and Xcode

  1. Create a UI using Swift in Xcode that has the button and label named Refresh IoT Temp. If needed, see the solution video for this lab to see how to deploy this UI from the Main.storyboard from the object library.
  2. Connect the UI with the code. If you need help, see the solution video for lab 1.
    The following code shows the basic functionality of the code without wiring with the Cloudant database:
    import UIKit
    //import SwiftCloudant from CocoaPods

    class ViewController: UIViewController {

    @IBOutlet weak var tempLabel: UILabel!
    private var jsonTemp = 0.0

    override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be re-created.
    }

    @IBAction func refreshButtonPressed(_ sender: Any) {
    NSLog("refresh IoT Temp button pressed")
    //get the temp
    //update the label
    tempLabel.text = "T= ?"
    }
    }

  3. When the code as shown above is working, close this project or close the Xcode editor.
  4. Add the SwiftCloudant CococaPods resource. You should get the CocoaPods with the latest Xcode. To get the latest update, in the terminal enter: sudo pod update
  5. Install the CocoaPods SwiftCloudant pod.
  6. Open a terminal and go to the project root directory that was selected when you created the iOS application. You should see the name of the application with the extension .xcodeproj.
  7. In the root directory of the application, initialize Podfile by issuing the command pod init
  8. Modify Podfile with the vim Podfile command.

  9. Uncomment platform and add pod ‘SwiftCloudant’. Then, press the Esc key and enter the vi editor command :wq to save the file and close the vim editor.
  10. Start the CocoaPods package manager by issuing the command pod install
  11. Open Xcode and instead of launching the xcodeproj, use the xcworkspace as it was described in the output of the CocoaPods project.
    In this example, it is the CheckIoTTemp.xcworkspace file as shown above. When you open CheckIoTTemp.xcworkspace from Xcode, you see your project with the additional Pods folders.
  12. Use the SwiftCloudant library in the code to access the database. You might need to build the code by entering cmd-B or by going to the Productmenu and selecting Build item before referring to the import SwiftCloudant library.
    When your code is built, you see the SwiftCloudant.framework under the Pods Products in the list as a solid yellow item. If it is not built, you might see the item in red.
  13. After the SwiftCloudant.framework appears in the Products list, import the library by using the command import SwiftCloudant
    import UIKit
    //import SwiftCloudant from CocoaPods
    import SwiftCloudant

    class ViewController: UIViewController {
    Now, you can use this library to do CRUD operations in the Cloudant database on Bluemix.

  14. Find the connection credentials in your Bluemix project.

  15. Use the following code to connect to the Cloudant database and read the JSON with the embedded temperature:
    //connect to Cloudant
    let cloudantUrl = NSURL(string: "cloudant db connection url")
    let cloudantClient = CouchDBClient(url: cloudantUrl! as URL, username: "cloudant db connection user", password: "cloudant db connection password")
    let database = "temperatures"

    //find the temp record
    let find = FindDocumentsOperation(selector: [:], databaseName: database, fields: ["payload", "timestamp"], limit: 1, skip: 0, sort: [Sort(field: "timestamp", sort: Sort.Direction.desc)], bookmark: nil, useIndex: nil, r: 1)
    { (response, httpInfo, error) in
    if let error = error {
    print("Encountered an error while reading a document. Error:\(error)")
    } else {
    print("Read document: \(response)")
    }
    }
    cloudantClient.add(operation:find)
    //update the label

  16. Parse the JSON data to get the temperature. Because the response JSON from the find query looks like the following console debug, you need to get to the nested part of the document that is highlighted in red:
    Read document: Optional(["warning": no matching index found, create an index to optimize query time, "docs": <__NSSingleObjectArrayI 0x608000007e90>(

    {
    payload = 40;
    timestamp = 20170201070636;
    }

    )
    ])
  17. Get the payload value of the temperature. To parse the JSON, use the following commands. Use the do – catch clause for the JSONSerialization exception catching:
    //get the temp value from JSON
    do {
    let data = try JSONSerialization.data(withJSONObject: response!, options: [])

    let parsedJson = try JSONSerialization.jsonObject(with: data, options: []) as! [String:Any]
    if let nestedArray = parsedJson["docs"] as? NSArray {

    print("nested \(nestedArray)")
    //getting nested temp from payload
    let newDoc = nestedArray[0] as? [String:Any]

    print("nested \(newDoc)")
    // access nested dictionary values by key

    let currentTemperature = newDoc?["payload"] as! Double

    print("found temp: \(currentTemperature)")
    self.jsonTemp = currentTemperature

    }

    } catch let error as NSError {
    print(error)
    }
    }

  18. Send the results to the UI of the smart device. You need to wait asynchronously to get the results sorted out by the SwiftCloudant library:
    //update the label
    //we need to wait for the results
    tempLabel.text = "T= ?"
    DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1), execute: {
    // Put your code which should be executed with a delay here
    NSLog("Read doc: 1 sec")
    self.tempLabel.text = "T = \(self.jsonTemp)"
    })

    The UI should look like this:

    Here is all of the code:
    import UIKit
    //import SwiftCloudant from CocoaPods
    import SwiftCloudant
    class ViewController: UIViewController {

    @IBOutlet weak var tempLabel: UILabel!
    private var jsonTemp = 0.0

    override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
    }
    @IBAction func refreshButtonPressed(_ sender: Any) {
    NSLog("refresh IoT Temp button pressed")

    //get the temp
    //connect to Cloudant
    let cloudantUrl = NSURL(string: "cloudant db connection url")
    let cloudantClient = CouchDBClient(url: cloudantUrl! as URL, username: "cloudant db connection user", password: "cloudant db connection password")
    let database = "temperatures"

    //find the temp record
    let find = FindDocumentsOperation(selector: [:], databaseName: database, fields: ["payload", "timestamp"], limit: 1, skip: 0, sort: [Sort(field: "timestamp", sort: Sort.Direction.desc)], bookmark: nil, useIndex: nil, r: 1)
    { (response, httpInfo, error) in
    if let error = error {
    print("Encountered an error while reading a document. Error:\(error)")
    } else {
    print("Read document: \(response)")

    //get the temp value from JSON
    do {
    let data = try JSONSerialization.data(withJSONObject: response!, options: [])

    let parsedJson = try JSONSerialization.jsonObject(with: data, options: []) as! [String:Any]
    if let nestedArray = parsedJson["docs"] as? NSArray {

    print("nested \(nestedArray)")
    //getting nested temp from payload
    let newDoc = nestedArray[0] as? [String:Any]

    print("nested \(newDoc)")
    // access nested dictionary values by key

    let currentTemperature = newDoc?["payload"] as! Double

    print("found temp: \(currentTemperature)")
    self.jsonTemp = currentTemperature

    }

    } catch let error as NSError {
    print(error)
    }
    }
    }
    cloudantClient.add(operation:find)
    //update the label
    //we need to wait for the results
    tempLabel.text = "T= ?"
    DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1), execute: {
    // Put your code which should be executed with a delay here
    NSLog("Read doc: 1 sec")
    self.tempLabel.text = "T = \(self.jsonTemp)"
    })

    }

    }