CloudKit Update a Record

In this lesson, you learn how to update record in the CloudKit’s public database. Here is a use case scenario of this CloudKit operation.

cloudkit-figure8-0

caution Code presented on this page assume you are using Xcode 6.4 and Swift version 1.2. So if you are using a newer version of Swift, it may produce errors. Fix them by using Xcode’s Fix-it tool. I assume you are a registered member of Apple’s iOS Developer Program, and you have a real iPhone/iPad device to test the CloudKit code presented here.

Modify The Main View

The first thing you have to do is change the storyboard’s button title and its class file so they look like this:

Figure 1
Figure 1

Now enter this statement in the MainViewController.swift file’s viewDidLoad() function:

//1. DISPLAY THE ITEM THE USER WILL EDIT ON THE VIEW'S CONTROLS
fetchRecordByItemName("iPod with headphone")

Next, enter this statement in the update() function:

//3.SAVE THE UPDATED ITEM IN THE PUBLIC DATABASE
updateTheRecord()

Here is the code to implement the functions called in the viewDidLoad() function and the update() function.

func fetchRecordByItemName(itemName: String) {
    let predicate = NSPredicate(format: "itemName = %@", itemName)
    let query = CKQuery(recordType: "Item", predicate: predicate)

    // Fetch the record for the itemName passed as a parameter to the function
    self.db.performQuery(query, inZoneWithID: nil, completionHandler: {results, error in
        if (error != nil) {
            println(error.localizedDescription)
        } else {
            if results.count == 0 {
                // On the main thread, update the textView
                NSOperationQueue.mainQueue().addOperationWithBlock {
                    self.textView.text = "Sorry, that item doesn't exists in the database."
                }
            } else {
                // Put the first record in the recordToUpdate variable
                self.recordToUpdate = results[0] as! CKRecord

                // On the main thread, add the recordToUpdate fields in the view's controls
                NSOperationQueue.mainQueue().addOperationWithBlock {
                    self.itemName.text = self.recordToUpdate.objectForKey("itemName") as! String
                    let photo = self.recordToUpdate.objectForKey("itemImage") as! CKAsset
                    self.imageView.image = UIImage(contentsOfFile: photo.fileURL.path!)
                }
            }
        }
    })
}

func updateTheRecord() {
    if let record = recordToUpdate {
        let item = DatabaseHeleper()
        let photoUrl = item.saveImageInDocumentsDir(self.imageView.image!)
        let asset = CKAsset(fileURL: photoUrl)
        record.setObject(itemName.text, forKey: "itemName")
        record.setObject(asset, forKey: "itemImage")

        self.db.saveRecord(record, completionHandler: {returnedRecord, error in
            if error != nil {
                NSOperationQueue.mainQueue().addOperationWithBlock {
                    self.textView.text = "Update error: \(error.localizedDescription)"
                }
            } else {
                NSOperationQueue.mainQueue().addOperationWithBlock {
                    self.textView.text = "Update successful."
                }
            }
        })
    }
}

Now, run the app in the iPhone 6 Simulator and you will see this output on the sim’s screen:

cloudkit-figure8-2
Figure 2

You will see output shown in Figure 3, when you clear out the textField and click the Update button. You will see output shown in Figure 4, when you enter a new item name in the textField, select a photo from the sim’s Photo Library, and click the Update button.

cloudkit-figure8-3 cloudkit-figure8-4
Figure 3 Figure 4

That’s it! Comments are welcomed! 🙂