Create a UI in Swift and Xcode
- 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.
- 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 CocoaPodsclass ViewController: UIViewController {
@IBOutlet weak var tempLabel: UILabel!
private var jsonTemp = 0.0override 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= ?"
}
} - When the code as shown above is working, close this project or close the Xcode editor.
- 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
- Install the CocoaPods SwiftCloudant pod.
- 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
. - In the root directory of the application, initialize
Podfile
by issuing the commandpod init
- Modify
Podfile
with thevim Podfile
command.
- Uncomment
platform
and addpod ‘SwiftCloudant’
. Then, press the Esc key and enter the vi editor command :wq
to save the file and close the vim editor. - Start the CocoaPods package manager by issuing the command
pod install
- 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 theCheckIoTTemp.xcworkspace
file as shown above. When you openCheckIoTTemp.xcworkspace
from Xcode, you see your project with the additional Pods folders.
- 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 theimport 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.
- 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 SwiftCloudantclass ViewController: UIViewController {
Now, you can use this library to do CRUD operations in the Cloudant database on Bluemix. - Find the connection credentials in your Bluemix project.
- 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 - 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;
}
)
]) - Get the
payload
value of the temperature. To parse the JSON, use the following commands. Use thedo – catch clause
for theJSONSerialization 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 keylet currentTemperature = newDoc?["payload"] as! Double
print("found temp: \(currentTemperature)")
self.jsonTemp = currentTemperature}
} catch let error as NSError {
print(error)
}
} - 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.0override 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 keylet 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)"
})}
}