How to properly send an image to CloudKit as CKAsset?
In my experience, the only way to save upload UIImage
as a CKAsset
is to:
- Save the image temporarily to disk
- Create the CKAsset
- Delete the temporary file
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)") }
// ...
}
I filed a bug report a few months ago requesting the ability to initialize
CKAsset
from in-memory NSData
, but it hasn't been done yet. Swift 3 Send image to CloudKit with CKAsset
Here is a simple way to save an image as a CKAsset
with CloudKit
. Please make sure to change the name for your Record, and the field name for the asset from when you set up the record.
let documentsDirectoryPath:NSString = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString
var imageURL: URL!
let tempImageName = "Image2.jpg"
func saveImage(_ image: UIImage?) {
// Create a CKRecord
let newRecord:CKRecord = CKRecord(recordType: "<INSERT_RECORD_NAME")
if let image = image {
let imageData:Data = UIImageJPEGRepresentation(image, 1.0)!
let path:String = self.documentsDirectoryPath.appendingPathComponent(self.tempImageName)
try? UIImageJPEGRepresentation(image, 1.0)!.write(to: URL(fileURLWithPath: path), options: [.atomic])
self.imageURL = URL(fileURLWithPath: path)
try? imageData.write(to: self.imageURL, options: [.atomic])
let File:CKAsset? = CKAsset(fileURL: URL(fileURLWithPath: path))
newRecord.setObject(File, forKey: "<INSERT_RECORD_ASSET_FIELD_NAME")
}
if let database = self.publicDatabase {
database.save(newRecord, completionHandler: { (record:CKRecord?, error:Error?) in
// Check if there was an error
if error != nil {
NSLog((error?.localizedDescription)!)
}
else if let record = record {
// Do whatever you want with the record, but image record was saved, asset should be saved.
}
})
}
}
If you can't do JPEG
format, and need to save as .png
you can substitute the UIImageJPEGRepresentation
section with this:
let imageData:Data = UIImagePNGRepresentation(image)!
try? UIImagePNGRepresentation(image)!.write(to: URL(fileURLWithPath: path), options: [.atomic])
And make the tempImageName
something like let tempImageName = "Image2.png"
Hope this helps
SwiftUI, CloudKit and Images
So, let's go... extract ForEach
image dependent internals into subview, like (of course it is not testable, just idea):
ForEach(gamesViewModel.games.indices, id: \.self) { index in
GeometryReader { proxy in
GameImageView(model: gamesViewModel, index: index) // << here !!
.frame(width: proxy.size.width, height: proxy.size.height)
.cornerRadius(1)
//.onDisappear { // if you think about cancelling
// gamesViewModel.cancelLoad(for: index)
//}
}
.ignoresSafeArea()
.offset(y: -100)
}
.onAppear(perform: loadImage)
and now subview itself
struct GameImageView: View {
var model: Your_model_type_here
var index: Int
@State private var image: UIImage? // << here !!
var body: some View {
Group {
if let loadedImage = image {
Image(uiImage: loadedImage) // << here !!
.resizable()
.aspectRatio(contentMode: .fill)
} else {
Text("Loading...")
}
}.onAppear {
model.getGameImageFromCloud(for: model.games[index]) { image in
self.image = image
}
}
}
}
How to upload images with cloud kit using swift?
You need to create a CKAsset and add that to your record. You can do that with code like this:
func SaveImageInCloud(ImageToSave: UIImage) {
let newRecord:CKRecord = CKRecord(recordType: "ImageRecord")
let nsDocumentDirectory = NSSearchPathDirectory.DocumentDirectory
let nsUserDomainMask = NSSearchPathDomainMask.UserDomainMask
if let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true) {
if paths.count > 0 {
if let dirPath = paths[0] as? String {
let writePath = dirPath.stringByAppendingPathComponent("Image2.png")
UIImagePNGRepresentation(ImageToSave).writeToFile(writePath, atomically: true)
var File : CKAsset? = CKAsset(fileURL: NSURL(fileURLWithPath: writePath))
newRecord.setValue(File, forKey: "Image")
}
}
}
if let database = self.privateDatabase {
database.saveRecord(newRecord, completionHandler: { (record:CKRecord!, error:NSError! ) in
if error != nil {
NSLog(error.localizedDescription)
} else {
dispatch_async(dispatch_get_main_queue()) {
println("finished")
}
}
})
}
Using Cloudkit Assets as a UIimage
Maybe the problem is that the CKAsset
record is nil, but you are forcing to have a fileURL
value.
Try to obtain CloudKit image with this snippet
if let asset = record["myImageKey"] as? CKAsset,
let data = try? Data(contentsOf: (asset.fileURL)),
let image = UIImage(data: data)
{
self.detailImage.image = image
}
How to store big image in CloudKit?
You should store pictures as a CKAsset. For a CKRecord there is a size limitation. For a CKAsset there is not (beside the CloudKit storage limitations). According to the documentation:
Use assets for discrete data files. When you want to associate images
or other discrete files with a record, use a CKAsset object to do so.
The total size of a record’s data is limited to 1 MB though assets do
not count against that limit.
You can create a CKAsset like this:
var File : CKAsset = CKAsset(fileURL: NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("image-not-available", ofType: "jpg")!))
How to receive an image from cloudkit?
Just read the CKRecord that you wrote and you can get the CKAsset by reading the key Image. You can get a UIImage using the code below.
var file : CKAsset? = record.objectForKey("Image")
func image() -> UIImage? {
if let file = file {
if let data = NSData(contentsOfURL: file.fileURL) {
return UIImage(data: data)
}
}
return nil
}
Related Topics
How to Remove the Bottom Gap of Uipageviewcontroller
Phimageresultisdegradedkey/Phimagefileurlkey Is Not Found
How to Unit Test an App Extension on Xcode 6
Makekeywindow VS Makekeyandvisible
Uipageviewcontroller Gesture Is Calling Viewcontrollerafter: But Doesn't Animate
Fbsopenapplicationerrordomain Code=3
Collectionview Duplicate Cell When Loading More Data
Using Wcsession with More Than One Viewcontroller
How to Create Scrollable Table in Skspritekit
Crashlytics Does Not Show Crashes
Check If 3D Touch Is Supported and Enabled on the iOS9 Device
How to Comment or Like a Photo in Facebook Through Fbconnect or Graph API in iPhone Sdk
iOS Autolayout - Frame Size Not Set in Viewdidlayoutsubviews
Uiwebview Not Go to Didfailloadwitherror When Weblink Not Found
Objective C- Trouble Updating UI on Main Thread
Why Was Uitextfield's Text Property Changed to an Optional in Swift 2
Get Created Date and Last Login Date from Firuser with Firebase 3