How to take a picture and save it to the app locally with swift

14,502

Solution 1

This is how you would store an image in NSUserDefaults:

As I mentioned in my comment, this is not recommended and, if used for more than one image, may result in serious performance loss and even crashes.

let image = UIImage(named: "myImage")
let pngImage = UIImagePNGRepresentation(image) 
            
NSUserDefaults.standardUserDefaults().setObject(pngImage, forKey: "image")
            
            

and to retrieve the image:

var retrievedImage = NSUserDefaults.standardUserDefaults().objectForKey("image") as! AnyObject

Then, to display the image:

imageView.image = UIImage(data: retrievedImage as! NSData)

This is how to store an image to a file (much better):

func saveImage (image: UIImage, path: String ) -> Bool{
    
    let pngImageData = UIImagePNGRepresentation(image)
    //let jpgImageData = UIImageJPEGRepresentation(image, 1.0)   // if you want to save as JPEG
    let result = pngImageData!.writeToFile(path, atomically: true)
    
    return result
    
}

You would call it like this:

saveImage(image, path: imagePath)

Then, to retrieve the image, use this function:

func loadImageFromPath(path: String) -> UIImage? {
    
    let image = UIImage(contentsOfFile: path)
    
    if image == nil {
        
        print("missing image at: \(path)")
    }
    print("Loading image from path: \(path)") // this is just for you to see the path in case you want to go to the directory, using Finder.
    return image
    
}

You can call it like this:

image = loadImageFromPath(imagePath)
        imageView.image = image

For more details, take a look at http://helpmecodeswift.com/image-manipulation/saving-loading-images

Also, you don't actually use the image that gets selected in your example, as Frederik pointed out.

You save an empty variable 'img' that has not been assigned to. You need to save 'image', the variable you get back after the picker has finished.

Here is how you get the image:

This function returns the variable 'image'

func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) {
picker.dismissViewControllerAnimated(true, completion: nil)

You can then go ahead and just use it e.g.

imageView.image = image  

or maybe

 saveImage(image, path: imagePath)  

Good luck!

Solution 2

Use this Method: with your image argument as below:

UIImageWriteToSavedPhotosAlbum(imagePicked, nil, nil, nil)

Solution 3

let fileDirectory : NSURL  = {
       return try! NSFileManager.defaultManager().URLForDirectory(.DocumentDirectory , inDomain: .UserDomainMask , appropriateForURL: nil, create: true)
   }()


func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) {
    picker.dismissViewControllerAnimated(true, completion: nil)

    //save to album 
    UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)

   //or to documents 
   //If you want to use png you have to change it later in saveImageToDocumentMethod in the guard statement
   saveImageToDocuments(image, filenameWithExtension: "test.jpg")
}


func saveImageToDocuments(image: UIImage, fileNameWithExtension: String){

       let imagePath = fileDirectory.URLByAppendingPathComponent("\(fileNameWithExtension)")

       guard let imageData = UIImageJPEGRepresentation(image, 1) else {
           // handle failed conversion
           print("jpg error")
           return
       }
       imageData.writeToFile((imagePath.path)!, atomically: true)

   }

When you want to use that image all you need to do is use the imagePath again and convert it into a UIImage.

Share:
14,502
acday
Author by

acday

Updated on June 10, 2022

Comments

  • acday
    acday almost 2 years

    I'm working on an app where in the current stage when a user takes a picture the picture will be stored locally within the app.

     @IBAction func CameraAction(sender: UIButton) {
    let picker = UIImagePickerController()
        picker.delegate = self
        picker.sourceType = .Camera
        picker.allowsEditing = true
        self.presentViewController(picker, animated: true, completion: nil)
    }
    
    func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) {
        picker.dismissViewControllerAnimated(true, completion: nil)
    
        //Save image
        let img = UIImage()
        let data = UIImagePNGRepresentation(img)
        NSUserDefaults.standardUserDefaults().setObject(data, forKey: "myImageKey")
        NSUserDefaults.standardUserDefaults().synchronize()
        NSLog("Image stored?")
        viewDidLoad()
    
    
    }
    

    From what I have above, my iPhone opens up its camera and I can take a picture. When I hit capture and the "use this image" option I don't think it the pictures are actually being stored because I haven't been able to recall the pictures.

    So I'm asking for help in how to locally store a picture taken from the UIImagePickerController, possibly in the documents folder, how to recall it, and how to do it without NSUserDEfaults. Thanks.

    • GJZ
      GJZ almost 8 years
      I would not recommend storing images in NSUserDefaults: the size of the image will cause crashes and enormous performance problems.
    • acday
      acday almost 8 years
      Right, I forgot to mention that I saw that it wasn't recommended. I'm looking for alternative methods of storing images I guess. Thanks.
    • FredericP
      FredericP almost 8 years
      You don't use the UIImage image for didFinishPickingImage. Shouldn't it be there?
  • acday
    acday almost 8 years
    When calling the saveimage function, what variable would I use for the UIImage? I don't know where or when I would define a UIImage variable that I guess comes from the UIImagePickerController.
  • GJZ
    GJZ almost 8 years
    @acday You already have the variable: it is provided by the function and has the name 'image'
  • Karthik Kannan
    Karthik Kannan almost 7 years
    Worked perfectly well for me in Swift 3. Thanks!