问题
I've a CKRecord type created in the CloudKit backend with some properties related to that class.
I've String properties, Bytes and I have a Asset List property, so store some images (multiple images related to a single record).
Now I'm trying so store some images and then fill the property and then trying to save it to CloudKit, but it's not working.
Code goes as it follows:
var images_array = [CKAsset]()
// append the an image to the array
images_array.append(CKAsset(fileURL: writeImage(image: selectedImage) as URL))
let record = CKRecord(recordType: recordName)
record["class_title"] = someString as CKRecordValue
record["class_body"] = someString as CKRecordValue
record["images_array"] = images_array as CKRecordValue
saveRecord(record)
func saveRecord(_ xrecord: CKRecord) {
let publicData = CKContainer.default().publicCloudDatabase
let record: [CKRecord] = [xrecord]
let saveOperation = CKModifyRecordsOperation.init(recordsToSave: record, recordIDsToDelete: nil)
saveOperation.perRecordCompletionBlock = {(record, error) -> Void in
if (error != nil) {
print("error")
}
}
publicData.add(saveOperation)
}
func writeImage(image: UIImage) -> URL {
let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let fileURL = NSURL(fileURLWithPath: documentsURL.absoluteString).appendingPathComponent(".jpg")
if let imageData = image.lowestQualityJPEGNSData {
do {
try imageData.write(to: fileURL!)
} catch {
print("ERRO 001 = \(error.localizedDescription)")
}
}
return fileURL!
}
extension UIImage {
var uncompressedPNGData: Data? { return UIImagePNGRepresentation(self) }
var highestQualityJPEGNSData: Data? { return UIImageJPEGRepresentation(self, 1.0) }
var highQualityJPEGNSData: Data? { return UIImageJPEGRepresentation(self, 0.75) }
var mediumQualityJPEGNSData: Data? { return UIImageJPEGRepresentation(self, 0.5) }
var lowQualityJPEGNSData: Data? { return UIImageJPEGRepresentation(self, 0.25) }
var lowestQualityJPEGNSData:Data? { return UIImageJPEGRepresentation(self, 0.0) }
}
If I only save the strings, everything works perfectly but with images it doesn't save the record.
I know there might be any issue with the appending, or I have to save the array in other way, or I shouldn't save it as CKRecordValue.
Do you have any tip on how to achieve this?
Thanks
回答1:
When you create your local asset file you should do so with the atomic write option. This will ensure that the file is completely written before CloudKit attempts to upload the asset.
This is the asset file creation function I use in the Seam 3 library:
fileprivate func createAsset(data: Data) -> CKAsset? {
var returnAsset: CKAsset? = nil
let tempStr = ProcessInfo.processInfo.globallyUniqueString
let filename = "\(tempStr)_file.bin"
let baseURL = URL(fileURLWithPath: NSTemporaryDirectory())
let fileURL = baseURL.appendingPathComponent(filename, isDirectory: false)
do {
try data.write(to: fileURL, options: [.atomicWrite])
returnAsset = CKAsset(fileURL: fileURL)
} catch {
print("Error creating asset: \(error)")
}
return returnAsset
}
回答2:
You have to take Array of CKAsset
for images.
var imageUrls = [CKAsset]()
Now get all images using for-loop. And save CKAsset of images.
for images in self.arrayImageSelected{
var myImage = UIImage()
if (images.isKindOfClass(PHAsset)){
let imageC = images as? PHAsset
myImage = self.getAssetThumbnail(imageC!)
}else if (images.isKindOfClass(UIImage)){
myImage = (images as? UIImage)!
}
let imagePath = self.storeImageAtDocumentDirectory(myImage, titleName: self.strTitle)
myPAth.append(imagePath)
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
let FbPath = paths.stringByAppendingString("/Custom")
let filePathToWrite = "\(FbPath)" + imagePath
let urls = NSURL(fileURLWithPath: filePathToWrite)
let imageAsset = CKAsset(fileURL: urls)
imageUrls.append(imageAsset)
}
Set Your array.
record.setObject(imageUrls, forKey: "images_array")
来源:https://stackoverflow.com/questions/43357769/saving-an-asset-list-array-to-specific-ckrecord