2

I have an iOS app in which there are 2 ways the user can get a picture:

  1. Select it from photos library (UIImagePickerController)

  2. Click it from a custom made camera

Here is my code for clicking the image from a custom camera (this is within a custom class called Camera, which is a subclass of UIView)

func clickPicture(completion:@escaping (UIImage) -> Void) {

    guard let videoConnection = stillImageOutput?.connection(withMediaType: AVMediaTypeVideo)  else { return }

    videoConnection.videoOrientation = .portrait
    stillImageOutput?.captureStillImageAsynchronously(from: videoConnection, completionHandler: { (sampleBuffer, error) -> Void in

        guard let buffer = sampleBuffer else { return }

        let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(buffer)
        let dataProvider = CGDataProvider(data: imageData! as CFData)
        let cgImageRef = CGImage(jpegDataProviderSource: dataProvider!, decode: nil, shouldInterpolate: true, intent: .defaultIntent)

        let image = UIImage(cgImage: cgImageRef!, scale: 1, orientation: .right)

        completion(image)


    })
}

Here is how I click the image within the ViewController:

@IBAction func clickImage(_ sender: AnyObject) {
    cameraView.clickPicture { (image) in
        //use "image" variable
    }
}

Later, I attempt to upload this picture to the user's iCloud account using CloudKit. However I receive an error saying the record is too large. I then came across this SO post, which says to use a CKAsset. However, the only constructor for a CKAsset requires a URL.

Is there a generic way I can get a URL from any UIImage? Otherwise, how can get a URL from the image I clicked using my custom camera (I have seen other posts about getting a url from a UIImagePickerController)? Thanks!

Community
  • 1
  • 1
Pranav Wadhwa
  • 7,666
  • 6
  • 39
  • 61

1 Answers1

1

CKAsset represents some external file (image, video, binary data and etc). This is why it requires URL as init parameter.

In your case I would recommend to use following steps to upload large image to CloudKit:

  1. Save UIImage to local storage (e.g. documents directory).
  2. Initialize CKAsset with path to image in local storage.
  3. Upload asset to Cloud.
  4. Delete image from local storage when uploading completed.

Here is some code:

// Save image.
let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
let filePath = "\(path)/MyImageName.jpg"

UIImageJPEGRepresentation(image, 1)!.writeToFile(filePath, atomically: true)

let asset = CKAsset(fileURL: NSURL(fileURLWithPath: filePath)!)
// Upload asset here.

// Delete image.
do {
    try FileManager.default.removeItem(atPath: filePath)
} catch {
    print(error)
}
Vlad Papko
  • 13,184
  • 4
  • 41
  • 57
  • Thanks for your response! However, I am obtaining the following error while saving the record to CloudKit: "No such file or directory". What could be causing this? – Pranav Wadhwa Nov 13 '16 at 21:48