如何正确地将图像作为CKAsset发送到CloudKit?

我有一个图像(UIImage,它也是url),我正在尝试将它作为CKAsset发送到CloudKit,但我遇到了这个错误: Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Non-file URL' 。 这是代码:

 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) } }) } 

我有URL,我可以打印,复制并粘贴到我的导航器,它将显示我的图像! 所以,我不知道这里发生了什么……

如果我使用UIImage而不是它的URL会更容易吗? 因为,正如我之前所说,我有两个! 任何帮助非常感谢! 多谢你们!!

根据我的经验,将上传UIImage保存为CKAsset的唯一方法是:

  1. 将映像临时保存到磁盘
  2. 创建CKAsset
  3. 删除临时文件

 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)") } // ... } 

我几个月前提交了一个错误报告,要求能够从内存中的NSData初始化CKAsset ,但尚未完成。

我做了一些不同的事情:我创建了一个可以在多个地方使用的类,并且由于Swift具有有效的重新初始化(与C ++不同),它会自行清理:

 // // 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)") } } } } 

这是一个练习它的unit 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)") } } 

本来打算把它作为UIImage的扩展,然后deist让我搬到了一个class级。

这是如何将图像保存到Cloudkit的Objective C版本

这需要相当多的挖掘,因为没有太多的信息可以继续,但这是有效的

  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); } }]; } }