Izzuddin Cheras Izzuddin Cheras - 10 months ago 109
Swift Question

ios swift play video uploaded from cloudkit

I am trying to play a video downloaded from cloudkit. I use the same query method that I use for downloading image:

publicData.performQuery(query, inZoneWithID: nil) { results, error in
if error == nil { // There is no error
for cafe in results! {
let newCafe = Cafe()
newCafe.address = cafe["address"] as? String
newCafe.name = cafe["name"] as? String
newCafe.email = cafe["email"] as? String
newCafe.description = cafe["description"] as? String
newCafe.location = cafe["location"] as? CLLocation
newCafe.cafeImage = cafe["cafeImage"] as? CKAsset
newCafe.offer_wifi = cafe["offer_wifi"] as? Bool
newCafe.smoking_area = cafe["smoking_area"] as? Bool
newCafe.cafeVideo = cafe["video"] as? CKAsset // <== I want to use this
let defaults: NSUserDefaults = NSUserDefaults.standardUserDefaults()

defaults.setInteger(self.cafes.count, forKey: "PreviousCafeCount")

dispatch_async(dispatch_get_main_queue(), { () -> Void in

inside the cafeDetailViewController, I create a button that trigger playing a video using AVPlayer. AVKit and AVFoundation are already imported.

@IBAction func playVideo(sender: AnyObject) {
if let file = cafeDetail.cafeVideo {
let player = AVPlayer(URL: file.fileURL)
let playerController = AVPlayerViewController()

playerController.player = player
playerController.view.frame = self.view.frame


However the result is this:enter image description here

follow up question: how can I implement model association in swift? Similar to has_many and belongs_to association in rails. I don't think downloading the whole video beforehand is a good solution.


From what I can see, you need to save the video to a local file and then play that file. This is modified from something I wrote to mess around with CloudKit.

    import UIKit
    import CloudKit
    import AVKit
    import AVFoundation

    class CloudKitTestViewController: UIViewController {

    let publicDatabase = CKContainer.defaultContainer().publicCloudDatabase

    var videoURL: NSURL!

    @IBAction func load(sender: AnyObject) {

        let predicate = NSPredicate(format: "videoName = %@", "nameOfVideoGoesHere")


        let query = CKQuery(recordType: "Videos", predicate: predicate)

        publicDatabase.performQuery(query, inZoneWithID: nil) { (results, error) in
            if error != nil {
                dispatch_async(dispatch_get_main_queue()) {
                    self.notifyUser("Cloud Access Error",
                                    message: error!.localizedDescription)
            } else {
                if results!.count > 0 {
                    let record = results![0]

                    dispatch_async(dispatch_get_main_queue()) {

                        let video = record.objectForKey("videoVideo") as! CKAsset

                        self.videoURL = video.fileURL 

                        let videoData = NSData(contentsOfURL: self.videoURL!)

                        let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0]
                        let destinationPath = NSURL(fileURLWithPath: documentsPath).URLByAppendingPathComponent("filename.mov", isDirectory: false)

                        NSFileManager.defaultManager().createFileAtPath(destinationPath.path!, contents:videoData, attributes:nil)

                        self.videoURL = destinationPath


                } else {
                    dispatch_async(dispatch_get_main_queue()) {
                        self.notifyUser("No Match Found",
                                        message: "No record matching the address was found")

            dispatch_async(dispatch_get_main_queue(), {


    override func prepareForSegue(segue: UIStoryboardSegue,
                                  sender: AnyObject?) {
        let destination = segue.destinationViewController as!
        let url = videoURL
        destination.player = AVPlayer(URL: url!)