Topics

#67: CloudKit Assets ⛅️

Topics

One of the best parts of CloudKit is how great it is at handling not just our models, but also larger assets like images, audio, or video.

Assets are saved just like any other property. Here we'll attach an image captured from the user's camera to a new record. Then we'll upload it to CloudKit using a CKModifyRecordsOperation (covered in more detail in Bite #31). In our case we're only saving a single record, but we're using an operation anyway, so we can take advantage of its perRecordProgressBlock, and track the upload progress of our asset.

func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
  guard let mediaURL = info[UIImagePickerControllerMediaURL] as? NSURL else { return }

  let spaceshipRecord = CKRecord(recordType: "Spaceship")

  spaceshipRecord["model"] = "Tantive IV"
  spaceshipRecord["maxSpeed"] = 950 // in km
  spaceshipRecord["image"] = CKAsset(fileURL: mediaURL)

  let operation = CKModifyRecordsOperation(recordsToSave: [spaceshipRecord], recordIDsToDelete: nil)

  operation.perRecordProgressBlock = { self.progressView.progress = $1 }
  operation.completionBlock = { self.progressView.hidden = true }

  progressView.hidden = false

  CKContainer.defaultContainer().publicCloudDatabase.addOperation(operation)
}

It's worth noting that CloudKit doesn't seem to report progress constantly as we might expect. It seems to report between 0-3 times depending on the size of the asset we're uploading.

After fetching a record containing an asset, we can grab the downloaded file from disk using the fileURL property of the CKAsset:

let asset = spaceshipRecord["image"] as! CKAsset

imageView.image = UIImage(
  contentsOfFile: asset.fileURL.absoluteString
)