21
// directoryPath is a URL from another VC
@IBAction func saveButtonTapped(sender: AnyObject) {
            let directoryPath           =  NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0] as NSURL
            let urlString : NSURL       = directoryPath.URLByAppendingPathComponent("Image1.png")
            print("Image path : \(urlString)")
            if !NSFileManager.defaultManager().fileExistsAtPath(directoryPath.absoluteString) {
                UIImageJPEGRepresentation(self.image, 1.0)!.writeToFile(urlString.absoluteString, atomically: true)
                displayImageAdded.text  = "Image Added Successfully"
            } else {
                displayImageAdded.text  = "Image Not Added"
                print("image \(image))")
            }
        }

I am not getting any error but the Image is not getting saved in the document.

Nishad Arora
  • 255
  • 1
  • 2
  • 10

8 Answers8

45

The problem there is that you are checking if the folder not exists but you should check if the file exists. Another issue in your code is that you need to use url.path instead of url.absoluteString. You are also saving a jpeg image using a "png" file extension. You should use "jpg".

edit/update:

Swift 4.2 or later

// get the documents directory url
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
// choose a name for your image
let fileName = "image.jpg"
// create the destination file url to save your image
let fileURL = documentsDirectory.appendingPathComponent(fileName)
// get your UIImage jpeg data representation and check if the destination file url already exists
if let data = image.jpegData(compressionQuality:  1.0),
  !FileManager.default.fileExists(atPath: fileURL.path) {
    do {
        // writes the image data to disk
        try data.write(to: fileURL)
        print("file saved")
    } catch {
        print("error saving file:", error)
    }
}
Leo Dabus
  • 198,248
  • 51
  • 423
  • 494
  • 2
    Note: You can also use writeToURL instead of adding .path! – Leo Dabus Sep 29 '15 at 07:08
  • 1
    It would be more helpful if you explained in your answer where the problem was, instead of just posting code. One cannot expect that future readers browse through all the comments to the question, and comments are even sometimes deleted. – Martin R Sep 29 '15 at 08:55
  • @MartinR Ok I will add the info – Leo Dabus Sep 29 '15 at 08:56
  • @LeoDabus : How to set name to downloaded image? – Jayprakash Dubey Sep 06 '17 at 06:46
  • @JayprakashDubey if you are using `URLSession` you can use the `suggestedFilename` property of the `URLResponse` https://developer.apple.com/documentation/foundation/urlresponse/1415924-suggestedfilename – Leo Dabus May 24 '18 at 16:21
26

This is my answer for Swift 3, combining the 2 answers above:

let documentsDirectoryURL = try! FileManager().url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
// create a name for your image
let fileURL = documentsDirectoryURL.appendingPathComponent("Savedframe.png")


if !FileManager.default.fileExists(atPath: fileURL.path) {
    do {
        try UIImagePNGRepresentation(imageView.image!)!.write(to: fileURL)
            print("Image Added Successfully")
        } catch {
            print(error)
        }
    } else {
        print("Image Not Added")
}
Harmlezz
  • 7,524
  • 23
  • 34
Roxana
  • 261
  • 3
  • 3
  • Where is image saved? Since I've used this code and 'Image Added Successfully' log is printed but unable to locate image in Photos.. – Jayprakash Dubey Sep 06 '17 at 06:25
5

An extension method in swift 4.2

import Foundation
import UIKit

extension UIImage {

    func saveToDocuments(filename:String) {
        let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
        let fileURL = documentsDirectory.appendingPathComponent(filename)
        if let data = self.jpegData(compressionQuality: 1.0) {
            do {
                try data.write(to: fileURL)
            } catch {
                print("error saving file to documents:", error)
            }
        }
    }

}
daviddna
  • 133
  • 2
  • 7
1
@IBAction func saveButtonTapped(sender: AnyObject) {
let directoryPath           =  try! NSFileManager().URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: true)    
let urlString : NSURL       = directoryPath.URLByAppendingPathComponent("Image1.png")
    print("Image path : \(urlString)")
    if !NSFileManager.defaultManager().fileExistsAtPath(urlString.path!) {
        UIImageJPEGRepresentation(self.image, 1.0)!.writeToFile(urlString.path! , atomically: true)
        displayImageAdded.text  = "Image Added Successfully"
    } else {
        displayImageAdded.text  = "Image Not Added"
        print("image \(image))")
    }
}
Nishad Arora
  • 255
  • 1
  • 2
  • 10
1

Put the image in an NSData object; writing to a file with this class is a breeze, and it'll make the file size smaller.

By the way, I recommend NSPurgeableData. After saving the image, you can mark the object as purgeable, which will keep memory consumption. That may be a problem with your app, but might be with another you're crowding out.

James Bush
  • 1,347
  • 11
  • 17
1

In Swift 4.2 and Xcode 10.1

func saveImageInDocsDir() {

    let image: UIImage? = yourImage//Here set your image
    if !(image == nil) {
        // get the documents directory url
        let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
        let documentsDirectory = paths[0] // Get documents folder
        let dataPath = URL(fileURLWithPath: documentsDirectory).appendingPathComponent("ImagesFolder").absoluteString //Set folder name
        print(dataPath)
        //Check is folder available or not, if not create 
        if !FileManager.default.fileExists(atPath: dataPath) {
            try? FileManager.default.createDirectory(atPath: dataPath, withIntermediateDirectories: true, attributes: nil) //Create folder if not
        }

        // create the destination file url to save your image
        let fileURL = URL(fileURLWithPath:dataPath).appendingPathComponent("imageName.jpg")//Your image name
        print(fileURL)
        // get your UIImage jpeg data representation
        let data = UIImageJPEGRepresentation(image!, 1.0)//Set image quality here
        do {
            // writes the image data to disk
            try data?.write(to: fileURL, options: .atomic)
        } catch {
            print("error:", error)
        }
    }
}
iOS
  • 11,881
  • 4
  • 71
  • 92
0

Although the answers are correct, I want to share utility functions for this purpose. You can use the following 2 methods to save and Image in Documents Directory and then load an image from Documents Directory. Here you can find the Detailed Article.

public static func saveImageInDocumentDirectory(image: UIImage, fileName: String) -> URL? {

        let documentsUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!;
        let fileURL = documentsUrl.appendingPathComponent(fileName)
        if let imageData = UIImagePNGRepresentation(image) {
            try? imageData.write(to: fileURL, options: .atomic)
            return fileURL
        }
        return nil
    }

public static func loadImageFromDocumentDirectory(fileName: String) -> UIImage? {

        let documentsUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!;
        let fileURL = documentsUrl.appendingPathComponent(fileName)
        do {
            let imageData = try Data(contentsOf: fileURL)
            return UIImage(data: imageData)
        } catch {}
        return nil
    }
Asad Ali Choudhry
  • 3,533
  • 4
  • 18
  • 31
0

Answer for Swift 5.x

func saveImageToDocumentsDirectory() {
        let directoryPath =  try! FileManager().url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
        let urlString : NSURL = directoryPath.appendingPathComponent("Image1.png") as NSURL
            print("Image path : \(urlString)")
        if !FileManager.default.fileExists(atPath: urlString.path!) {
            do {
                try self.image.jpegData(compressionQuality: 1.0)!.write(to: urlString as URL)
                print ("Image Added Successfully")
            } catch {
                print ("Image Not added")
            }
        }
    }

Note : image = your declared image.