¿Cómo enviar correctamente una image a CloudKit como CKAsset?

Tengo una image (UIImage y su url también) e bash enviarla a CloudKit como un CKAsset, pero tengo este error: Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Non-file URL' . Aquí está el código:

 override func viewDidLoad() { super.viewDidLoad() send2Cloud() } func send2Cloud() { let newUser = CKRecord(recordType: "User") let url = NSURL(string: self.photoURL) let asset = CKAsset(fileURL: url!) newUser["name"] = self.name newUser["photo"] = asset let publicData = CKContainer.defaultContainer().publicCloudDatabase publicData.saveRecord(newUser, completionHandler: { (record: CKRecord?, error: NSError?) in if error == nil { dispatch_async(dispatch_get_main_queue(), { () -> Void in print("User saved") }) } else { print(error?.localizedDescription) } }) } 

¡Tengo la URL, puedo imprimirla, copyrla y pegarla en mi browser y mostrará mi image! Entonces, no sé qué está pasando aquí …

¿Sería más fácil si trabajara con un UIImage en lugar de su URL? ¡Porque, como lo he dicho antes, los tengo a ambos! ¡Se agradece mucho cualquier ayuda! ¡¡Gracias chicos!!

En mi experiencia, la única forma de save UIImage subido como un CKAsset es:

  1. Guardar la image temporalmente en el disco
  2. Crea el CKAsset
  3. Eliminar el file temporal

 let data = UIImagePNGRepresentation(myImage); // UIImage -> NSData, see also UIImageJPEGRepresentation let url = NSURL(fileURLWithPath: NSTemporaryDirectory()).URLByAppendingPathComponent(NSUUID().UUIDString+".dat") do { try data!.writeToURL(url, options: []) } catch let e as NSError { print("Error! \(e)"); return } newUser["photo"] = CKAsset(fileURL: url) // ... publicData.saveRecord(newUser, completionHandler: { (record: CKRecord?, error: NSError?) in // Delete the temporary file do { try NSFileManager.defaultManager().removeItemAtURL(url) } catch let e { print("Error deleting temp file: \(e)") } // ... } 

Presenté un informe de errores hace unos meses solicitando la capacidad de inicializar CKAsset desde CKAsset en memory, pero aún no se ha hecho.

Hice algo un poco diferente: hice una class que puedes usar en varios lugares, y gracias al hecho de que Swift tiene una reinitialization que funciona (a diferencia de C ++), se limpia después de sí misma:

 // // ImageAsset.swift // import CloudKit import UIKit class ImageAsset { let image:UIImage var url:NSURL? var asset:CKAsset? { get { let data = UIImagePNGRepresentation(self.image) self.url = NSURL(fileURLWithPath: NSTemporaryDirectory()).URLByAppendingPathComponent(NSUUID().UUIDString+".dat") if let url = self.url { do { try data!.writeToURL(url, options: []) } catch let e as NSError { print("Error! \(e)") } return CKAsset(fileURL: url) } return nil } } init(image:UIImage){ self.image = image } deinit { if let url = self.url { do { try NSFileManager.defaultManager().removeItemAtURL(url) } catch let e { print("Error deleting temp file: \(e)") } } } } 

Aquí hay una testing de unidad que la ejerce (presume que hay una image llamada cronómetro en el objective de testing):

 // // ImageExtensionTests.swift // import CloudKit import XCTest @testable import BudgetImpactEstimator class ImageExtensionTests: XCTestCase { let testImageName = "stopwatch" // provide the name of an image in test bundle override func setUp() { super.setUp() // Put setup code here. This method is called before the invocation of each test method in the class. } override func tearDown() { // Put teardown code here. This method is called after the invocation of each test method in the class. super.tearDown() } func testConvertingImageToAsset() { guard let image = UIImage(named: self.testImageName) else { XCTFail("failed to load image") return } let imageAsset = ImageAsset(image: image) XCTAssertNotNil(imageAsset) guard let asset = imageAsset.asset else { XCTFail("failed to get asset from image") return } print("constructed asset: \(asset)") } } 

Originalmente iba a hacerlo como una extensión de UIImage, pero luego el deísta me hizo pasar a una class.

Esta es la versión de Objective C de cómo save una image en Cloudkit.

Esto tomó un poco de excavación ya que no hay mucha información para continuar, pero esto funciona

  if([results count] <= 0) { NSLog(@"this Record doesnt exist so add it ok!! %@", error); CKRecordID *wellKnownID = [[CKRecordID alloc] initWithRecordName:idString]; CKRecord *entitiesName = [[CKRecord alloc] initWithRecordType:@"mySavedDetails" recordID:wellKnownID]; [entitiesName setObject:idString forKey:@"myDetailsId"]; [entitiesName setObject:self.myName.text forKey:@"myName"]; if (myUIImage.image != nil) { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSString* path = [documentsDirectory stringByAppendingPathComponent: @"test.png" ]; NSData* data = UIImagePNGRepresentation(myUIImage.image.image); [data writeToFile:path atomically:YES]; //so we get the full path of the uiimage NSLog(@"Path details %@",path); NSURL* myImagePath = nil; myImagePath = [[NSBundle mainBundle] URLForResource:path withExtension:@"png"]; //here we change the path of Image which is a string to a URL NSURL *yourURL = [NSURL fileURLWithPath:path]; CKAsset* myImageAsset = nil; myImageAsset = [[CKAsset alloc] initWithFileURL:yourURL]; [entitiesName setObject: myImageAsset forKey:@"myImage"]; [publicDatabase saveRecord: entitiesName completionHandler:^(CKRecord *savedState, NSError *error) { if (error) { NSLog(@"ERROR SAVING: %@", error); } }]; } }