CloudKit Delete a Record

In this lesson you learn how to perform the CloudKit operation that delete a single record from the CloudKit’s public database. Start by going to the CloudKit Dashboard and add these Items in the public database’s Default Zone.

cloudkit-figure9-1

Figure 1

Now, launch the CloudKitGuide project in Xcode and modify the storyboard scene and its class file so then look like Figure 2 and Figure 3:

Figure 2

Figure 2: The Main View Controller scene

Figure 3

Figure 3: The MainViewController class

When you run the app in the iPhone 6 Simulator, the Main View will look like this:

Figure 4

Figure 4

Ok, enter code shown below in the pickerView’s delegate functions.

// Mark: - UIPierViewDelegate functions
func pickerView(pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusingView view: UIView!) -> UIView {
  // Create a UIView
  var view = UIView(frame: CGRectMake(0, 0, 110, 60))

  for var i = 0; i < itemPhotoList.count; i++ {
    // Create and initialize an ImageView
    let imageView = UIImageView(frame: CGRectMake(0, 0, 55, 60))
    imageView.image = itemPhotoList[row]

    // Create and initialize a Label
    let labelView = UILabel(frame: CGRectMake(60, 15, 145, 30))
    labelView.text = itemNameList[row]

    // Add the imageView and the Label view to the UIView
    view.addSubview(imageView)
    view.addSubview(labelView)

    // Highlight the pickerView selector
    counter++
    var overlayOnPicker:UIView = UIView(frame: CGRectMake(1, 78, pickerView.frame.width, 60))
    if counter < 3 {
      overlayOnPicker.alpha = 0.05
      overlayOnPicker.backgroundColor = UIColor.yellowColor()
    }
    pickerView.addSubview(overlayOnPicker)
  }
  return view
}

func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
  // The user selected row in the pickerView, add it in the selectedItemName variable
  selectedItemName = itemNameList[row]

  // Set the textView
  self.textView.text = "Item selected, " + selectedItemName +
  ".\n\nTap the Delete button to delete it from the pick view."
}

Code you entered in the pickerView’s reusingView() functions pretty much highlight the pickerView selector and populate the pickerView with data stored in its dataSources; which are these array variables:

  • itemNameList – This array hold item names fetched from the public database.
  • itemPhotoList – This array holds items photos fetched from the public database.

As for the pikerView’s didSelectRow() function, it is fired when the user scroll the pickerView to select an item. Code you entered in the function set the selectedItemName variable and the textView.

What you have to do now is add code in the MainViewController class file to fetch all records from the public database and add them in the pickerView’s dataSource arrays. Here’s the code to do that. By the way, the sortDescriptor code put the fetched records in alphabetical order.

func fetchAllRecords() {
  // Setup a query with with a predicate and a sortDescriptor
  let predicate = NSPredicate(value: true)
  let query = CKQuery(recordType: "Item", predicate: predicate)
  let sortDescriptor = NSSortDescriptor(key: "itemName", ascending: true)
  query.sortDescriptors = [sortDescriptor]

  // Perform the query on the public database
  self.db.performQuery(query, inZoneWithID: nil) {
    records, error in
    if error != nil {
      // The query returned an error, show it in the textView
      println("Fetch all records error: \(error.localizedDescription)")
    } else {
      // The query return one or more records
      for record in records {
        // Set the item object's properties with the CKRecord and the CKAsset fetched from the CloudKit public database
        let asset: CKAsset = record.valueForKey("itemImage") as! CKAsset
        let photo = UIImage(contentsOfFile: asset.fileURL.path!)
        let itemName = record.valueForKey("itemName") as! String

        // Add the current item record fields in arrays
        self.itemPhotoList.append(photo!)
        self.itemNameList.append(itemName)
      }

      // On the main thread, refresh the pickerView components (columns)
      NSOperationQueue.mainQueue().addOperationWithBlock {
        self.pickerView.reloadAllComponents()
      }
    }
  }
}

Call the fetchAllRecords() function in the viewDidLoad() function.

// Populate the pickerView control with items stored in the public database
fetchAllRecords()

Next, implement this user defined function in the MainViewController class file.

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

    // Fetch the record to delete from the public database
    self.db.performQuery(query, inZoneWithID: nil) {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 recordToDelete variable
                let recordToDelete: CKRecord! = results.first as! CKRecord

                if let record = recordToDelete {
                    self.db.deleteRecordWithID(record.recordID) {result, error in
                        if error != nil {
                            NSOperationQueue.mainQueue().addOperationWithBlock {
                                self.textView.text = "Delete error: \(error.localizedDescription)"
                            }
                        } else {
                            NSOperationQueue.mainQueue().addOperationWithBlock {
                                self.textView.text = "The record was deleted from the database."
                                self.itemNameList.removeAll(keepCapacity: false)
                                self.itemPhotoList.removeAll(keepCapacity: false)
                                self.fetchAllRecords()
                            }
                        }
                    }
                }
            }
        }
    }
}

Code you entered in the deleteDatabaseRecord() function fetch the record the user wants to delete from the public database, put it in a constant called recordToDelete, then delete it from the public database.

Finally, call the deleteDatabase() function in the delete() function, then run the app in the iPhone 6 Simulator.

// Delete the selected item from the public database
deleteDatabaseRecord()

You will see output shown in Figure 5, on the sim’s screen. When you select a row in the pickerView, you will see output shown in Figure 6. Figure 7 shows result of deleting the selected item from the pickerView.

Figure 5

Figure 5

Figure 6

Figure 6

Figure 7

Figure 7

Now, go to the CloudKit Dashboard to verify that the item you deleted from the pickerView control was indeed, deleted from the public database’s Default Zone. As you can see in Figure 8 below; the item, “Programming Books” was deleted from the public database.

Figure 8

Figure 8

 

That’s it! Now you know how to perform the CloudKit operation that delete a single record from the CloudKit’s public database. Comments are welcomed! 🙂