Lion Gurman Lion Gurman - 1 month ago 14
Swift Question

Save image in Realm

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

Answer

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: Utils.getDocumentsDirectory().appendingPathComponent(timestampFilename))
                let imgData = try! imageData?.write(to: filenamePath, options: [])

            })
Comments