Obtaining CKAsset URL without downloading data

I use CloudKit in my application to remotely delete data. One of my entries has a CKAsset property that contains an image. When I collect the records, I realized that it took so long to complete the request. After several tests, I came to the conclusion that when requesting records, CloutKit downloads the entire Asset file with the record object. Therefore, when you get the Asset from the recording object and request the fileURL file, it gives the URL of the local file path, not the HTTP type URL. This is like a problem for me, because you have to let the user wait so much time that all records are loaded (with the images associated with them) until the request is completed. Based on the Parse background, Parse is used to provide you with an HTTP URL, and the request is fast enough to load the user interface with objects when loading async images. My question is, how can I achieve what Pars does? I need to limit requests from downloading Assets data and get a link to download images asynchronously.

+6
source share
3 answers

You can use CloudKit JavaScript to access the asset url. Here is an example:

(Used by Alamofire and SwiftyJSON )

func testRecordRequest() -> Request { let urlString = "https://api.apple-cloudkit.com/database/1/" + Constants.container + "/development/public/records/query?ckAPIToken=" + Constants.cloudKitAPIToken let query = ["recordType": "TestRecord"] return Alamofire.request(.POST, urlString, parameters: ["query": query], encoding: .JSON, headers: nil) } 

The JSON response contains "downloadURL" for the asset.

 "downloadURL": "https://cvws.icloud-content.com/B/.../${f}?o=AmVtU..." 

"$ {f}" is like a variable, so change it to whatever you like.

 let downloadURLString = json["fields"][FieldNames.image]["value"]["downloadURL"].stringValue let recordName = json["recordName"].stringValue let fileName = recordName + ".jpg" let imageURLString = downloadURLString.stringByReplacingOccurrencesOfString("${f}", withString: fileName) 

And now we can use this urlString to create an NSURL and use it with any image and cache solutions like Kingfisher, HanekeSwift, etc. (You can also save the image type png / jpg)

+4
source

Make two separate calls for the same entry. The first call should receive all the required fields of NON assets, and then the second request should receive the required assets.

Sort of:

 let dataQueryOperation = CKQueryOperation(query: CKQuery(predicate: myPredicate) dataQueryOperation.desiredKeys = ["name", "age"] // etc database.addOperation(dataQueryOperation) let imageQueryOperation = CKQueryOperation(query: CKQuery(predicate: myPredicate) imageQueryOperation.desiredKeys = ["images"] database.addOperation(imageQueryOperation) 

If necessary, reformat this to a method so that you can easily create a new CKQueryOperation for each field containing the assets.

Happy hunt.

+1
source

Like others, you cannot get the URL of CKAsset. Thus, your best options are: 1. Use a fetch operation with progress on each UIImageView. I created a custom one that shows the progress for the user. The cache is not included, but you can create a class and accept NSCoding and save the entire entry in the cache. Here you can see a selection in which I have a completion to send the object back to where I call it, to combine it with my other data.

  // only get the asset in this fetch. we have everything else 

let operation = CKFetchRecordsOperation (recordIDs: [myRecordID])

  operation.desiredKeys = ["GameTurnImage"] operation.perRecordProgressBlock = { record,progress in dispatch_async(dispatch_get_main_queue(), { self.progressIndicatorView.progress = CGFloat(progress) }) } operation.perRecordCompletionBlock = { record,recordID,error in if let _ = record{ let asset = record!.valueForKey("GameTurnImage") as? CKAsset if let _ = asset{ let url = asset!.fileURL let imageData = NSData(contentsOfFile: url.path!)! dispatch_async(dispatch_get_main_queue(), { self.image = UIImage(data: imageData) self.progressIndicatorView.reveal() }) completion(asset!) } } } CKContainer.defaultContainer().publicCloudDatabase.addOperation(operation) 

Another option is to store the images on an AWS server or something comparable, and then you can use something like SDWebImage to do the whole cache or heavy lifting and save the line in CKRecord for the image.

I asked several people about the CKAsset function to open the URL. I don't know about JS Api for CloudKit, but there may be a way to do this with this, but I will let others chat with it.

0
source

All Articles