7

I'm trying to pick image from device's Photo Library in method:

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any])
{

    userPhoto.image = info[UIImagePickerControllerOriginalImage] as! UIImage?
    userPhoto.contentMode = .scaleAspectFill
    userPhoto.clipsToBounds = true

    dismiss(animated: true, completion: nil)
}

and save this picture in Realm (as NSData):

asset.assetImage = UIImagePNGRepresentation(userPhoto.image!)! as NSData?

...

   try! myRealm.write
        {
            user.assetsList.append(asset)
            myRealm.add(user)
        }

After build succeeded and trying to pick and save image (in the app) i have app error: 'Binary too big'

What i'm doing wrong?

P.S. Sorry for my English :)


After some actions i have this code. But it's overwrite my image.

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any])
{
    let imageUrl = info[UIImagePickerControllerReferenceURL] as! NSURL
    let imageName = imageUrl.lastPathComponent
    let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
    let photoURL = NSURL(fileURLWithPath: documentDirectory)
    let localPath = photoURL.appendingPathComponent(imageName!)
    let image = info[UIImagePickerControllerOriginalImage]as! UIImage
    let data = UIImagePNGRepresentation(image)

    do
    {
        try data?.write(to: localPath!, options: Data.WritingOptions.atomic)
    }
    catch
    {
        // Catch exception here and act accordingly
    }

    userPhoto.image = image
    userPhoto.contentMode = .scaleAspectFill
    userPhoto.clipsToBounds = true

    urlCatch = (localPath?.path)!
    self.dismiss(animated: true, completion: nil);
}
Lion Gurman
  • 161
  • 1
  • 2
  • 9
  • 1
    debug and print your imageName let imageName = imageUrl.lastPathComponent if it's always the same name, the image gets overridden. the image name must be unique. something like let timestampFilename = String(Int(Date().timeIntervalSince1970)) + "_newImage.png" – Peter Pohlmann Oct 21 '16 at 12:03
  • It works great! Thank you very much! – Lion Gurman Oct 21 '16 at 12:55

3 Answers3

15

Don't save the image itself into realm, just save the location of the image into realm as String or NSString and load the image from that saved path. Performance wise it's always better to load images from that physical location and your database doesn't get too big

  func loadImageFromPath(_ path: NSString) -> UIImage? {

        let image = UIImage(contentsOfFile: path as String)

        if image == nil {
            return UIImage()
        } else{
            return image
        }
    }

or you just save the image name, if it's in your documents directory anyhow

func loadImageFromName(_ imgName: String) -> UIImage? {

        guard  imgName.characters.count > 0 else {
            print("ERROR: No image name")
            return UIImage()
        }

        let imgPath = Utils.getDocumentsDirectory().appendingPathComponent(imgName)
        let image = ImageUtils.loadImageFromPath(imgPath as NSString)           
        return image    
    }

and here a rough example how to save a captured image to your directory with a unique name:

    @IBAction func capture(_ sender: AnyObject) {

        let videoConnection = stillImageOutput?.connection(withMediaType: AVMediaTypeVideo)
            stillImageOutput?.captureStillImageAsynchronously(from: videoConnection, completionHandler: { (imageDataSampleBuffer, error) -> Void in

                let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageDataSampleBuffer)
                //self.stillImage = UIImage(data: imageData!)
                //self.savedImage.image = self.stillImage

                let timestampFilename = String(Int(Date().timeIntervalSince1970)) + "someName.png"

                let filenamePath =  URL(fileReferenceLiteralResourceName: getDocumentsDirectory().appendingPathComponent(timestampFilename))
                let imgData = try! imageData?.write(to: filenamePath, options: [])

            })



    /* helper get Document Directory */
    class func getDocumentsDirectory() -> NSString {
        let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
        let documentsDirectory = paths[0]
        //print("Path: \(documentsDirectory)")
        return documentsDirectory as NSString
    }
Peter Pohlmann
  • 1,478
  • 15
  • 30
  • Thx for answer! Save capture image - it means i have copy image from PhotoLibrary to image Directory of my app? Can you tell me how i can get path(NSURL) of captured image in didFinishPickingMediaWithInfo method? – Lion Gurman Oct 20 '16 at 13:48
  • have a look here: http://stackoverflow.com/questions/33085409/getting-url-of-uiimage-from-uiimagepickercontroller – Peter Pohlmann Oct 20 '16 at 13:53
  • 1. when i'm trying to save picture it's rewriting. – Lion Gurman Oct 21 '16 at 10:08
  • 2. when i'm restart my app (in simulator) - i have no images (been before) – Lion Gurman Oct 21 '16 at 10:10
  • what you mean with rewriting? overwriting? check if the image name is unique for every image when you you use the simulator the images only lives in that specific simulator instance. if you reset the simulator, the images are gone. that's normal. on our phone they will stay in your app directoy – Peter Pohlmann Oct 21 '16 at 10:13
  • i have edit my question and add code what i have now. What's wrong with it? – Lion Gurman Oct 21 '16 at 10:39
5

https://realm.io/docs/objc/latest/#current-limitations maximum data size is 16 MB . this is limitation of realm

Vyacheslav
  • 26,359
  • 19
  • 112
  • 194
0

Depending on how your serializing the image data (for example if it's a lossless bitmap), it's quite possible that this data exceed 16MB, which as you've stated is Realm's maximum supported size for binary properties.

When you invoke NSData.length, how large does it say your data is?

hussain
  • 769
  • 2
  • 7
  • 24