Saving image and then loading it in Swift (iOS)
Solution 1
This function will save an image in the documents folder:
func saveImage(image: UIImage) -> Bool {
guard let data = UIImageJPEGRepresentation(image, 1) ?? UIImagePNGRepresentation(image) else {
return false
}
guard let directory = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) as NSURL else {
return false
}
do {
try data.write(to: directory.appendingPathComponent("fileName.png")!)
return true
} catch {
print(error.localizedDescription)
return false
}
}
To use:
let success = saveImage(image: UIImage(named: "image.png")!)
This function will get that image:
func getSavedImage(named: String) -> UIImage? {
if let dir = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) {
return UIImage(contentsOfFile: URL(fileURLWithPath: dir.absoluteString).appendingPathComponent(named).path)
}
return nil
}
To use:
if let image = getSavedImage(named: "fileName") {
// do something with image
}
Solution 2
iOS 13+ Swift 5.1
iOS 12 introduced some API Changes.
func saveImage(imageName: String, image: UIImage) {
guard let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
let fileName = imageName
let fileURL = documentsDirectory.appendingPathComponent(fileName)
guard let data = image.jpegData(compressionQuality: 1) else { return }
//Checks if file exists, removes it if so.
if FileManager.default.fileExists(atPath: fileURL.path) {
do {
try FileManager.default.removeItem(atPath: fileURL.path)
print("Removed old image")
} catch let removeError {
print("couldn't remove file at path", removeError)
}
}
do {
try data.write(to: fileURL)
} catch let error {
print("error saving file with error", error)
}
}
func loadImageFromDiskWith(fileName: String) -> UIImage? {
let documentDirectory = FileManager.SearchPathDirectory.documentDirectory
let userDomainMask = FileManager.SearchPathDomainMask.userDomainMask
let paths = NSSearchPathForDirectoriesInDomains(documentDirectory, userDomainMask, true)
if let dirPath = paths.first {
let imageUrl = URL(fileURLWithPath: dirPath).appendingPathComponent(fileName)
let image = UIImage(contentsOfFile: imageUrl.path)
return image
}
return nil
}
Solution 3
Details
- Xcode Version 10.2 (10E125), Swift 5
Solution
// save
extension UIImage {
func save(at directory: FileManager.SearchPathDirectory,
pathAndImageName: String,
createSubdirectoriesIfNeed: Bool = true,
compressionQuality: CGFloat = 1.0) -> URL? {
do {
let documentsDirectory = try FileManager.default.url(for: directory, in: .userDomainMask,
appropriateFor: nil,
create: false)
return save(at: documentsDirectory.appendingPathComponent(pathAndImageName),
createSubdirectoriesIfNeed: createSubdirectoriesIfNeed,
compressionQuality: compressionQuality)
} catch {
print("-- Error: \(error)")
return nil
}
}
func save(at url: URL,
createSubdirectoriesIfNeed: Bool = true,
compressionQuality: CGFloat = 1.0) -> URL? {
do {
if createSubdirectoriesIfNeed {
try FileManager.default.createDirectory(at: url.deletingLastPathComponent(),
withIntermediateDirectories: true,
attributes: nil)
}
guard let data = jpegData(compressionQuality: compressionQuality) else { return nil }
try data.write(to: url)
return url
} catch {
print("-- Error: \(error)")
return nil
}
}
}
// load from path
extension UIImage {
convenience init?(fileURLWithPath url: URL, scale: CGFloat = 1.0) {
do {
let data = try Data(contentsOf: url)
self.init(data: data, scale: scale)
} catch {
print("-- Error: \(error)")
return nil
}
}
}
Usage
// save image (way 1)
let path = "photo/temp/album1/img.jpg"
guard let img = UIImage(named: "img"),
let url = img.save(at: .documentDirectory,
pathAndImageName: path) else { return }
print(url)
// get image from directory
guard let img2 = UIImage(fileURLWithPath: url) else { return }
// save image (way 2)
let tempDirectoryUrl = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(path)
guard let url2 = img2.save(at: tempDirectoryUrl) else { return }
print(url2)
Check results
open the iOS simulator directory
Solution 4
You should save image name with extension so your path should be like,
///var/mobile/Applications/BDB992FB-E378-4719-B7B7-E9A364EEE54B/Documents/tempImage.png
And second thing replace below line,
let result = pngImageData!.writeToFile(path, atomically: true)
with
let result = pngImageData!.writeToFile(path, atomically: false)
You need to set false as parameter of atomically
.
atomically:
If true, the data is written to a backup file, and then—assuming no errors occur—the backup file is renamed to the name specified by path; otherwise, the data is written directly to path.
Hope this will help :)
Solution 5
Save image in local Xcode Documents directory
Pass in your image and the name you want to call it (you choose what you want fileName to be).
func saveImageLocally(image: UIImage, fileName: String) {
// Obtaining the Location of the Documents Directory
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
// Creating a URL to the name of your file
let url = documentsDirectory.appendingPathComponent(fileName)
if let data = image.pngData() {
do {
try data.write(to: url) // Writing an Image in the Documents Directory
} catch {
print("Unable to Write \(fileName) Image Data to Disk")
}
}
}
Read
Use the same fileName as when you saved it
func getImageFromName(fileName: String) {
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let url = documentsDirectory.appendingPathComponent(fileName)
if let imageData = try? Data(contentsOf: url) {
let image = UIImage(data: imageData) // HERE IS YOUR IMAGE! Do what you want with it!
} else {
print("Couldn't get image for \(fileName)")
}
}
![tesgoe](https://i.stack.imgur.com/J4tKI.png?s=256&g=1)
tesgoe
Updated on July 09, 2022Comments
-
tesgoe almost 2 years
I am saving an image using saveImage.
func saveImage (image: UIImage, path: String ) -> Bool{ let pngImageData = UIImagePNGRepresentation(image) //let jpgImageData = UIImageJPEGRepresentation(image, 1.0) // if you want to save as JPEG print("!!!saving image at: \(path)") let result = pngImageData!.writeToFile(path, atomically: true) return result }
New info:
Saving file does not work properly ("[-] ERROR SAVING FILE" is printed)--
// save your image here into Document Directory let res = saveImage(tempImage, path: fileInDocumentsDirectory("abc.png")) if(res == true){ print ("[+] FILE SAVED") }else{ print ("[-] ERROR SAVING FILE") }
Why doesn't the saveImage function save the image? Access rights?
Older info:
The debug info says:
!!!saving image at: file:///var/mobile/Applications/BDB992FB-E378-4719-B7B7-E9A364EEE54B/Documents/tempImage
Then I retrieve this location using
fileInDocumentsDirectory("tempImage")
The result is correct.
Then I am loading the file using this path
let image = UIImage(contentsOfFile: path) if image == nil { print("missing image at: \(path)") }else{ print("!!!IMAGE FOUND at: \(path)") }
The path is correct, but the message is "missing image at..". Is the file somehow inaccessible or not stored? What can be a reason for this behavior?
I am testing this code on iphone 4 with ios 7 and iphone 5 with ios 7 simulator.
Edit: 1. The fileInDocumentsDirectory function
func fileInDocumentsDirectory(filename: String) -> String { let documentsURL = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0] let fileURL = documentsURL.URLByAppendingPathComponent(filename).absoluteString return fileURL }
-
tesgoe about 8 yearsHi, I did that, but it still does not work -- !!!save: file:///var/mobile/Applications/E78F2521-929E-4E4D-834F-57C07A62DB84/Documents/tempImage.png !!!miss: file:///var/mobile/Applications/E78F2521-929E-4E4D-834F-57C07A62DB84/Documents/tempImage.png !!!miss: file:///var/mobile/Applications/E78F2521-929E-4E4D-834F-57C07A62DB84/Documents/tempImage.png
-
Ketan Parmar about 8 yearsMake sure your image is not nil!! and you are passing path in
let image = UIImage(contentsOfFile: path)
is exact same as you write it and this path should be with extension. And once try to retrieve inNSData
instead ofUIImage
from this path. If you got data then that means there is a problem to convert it in image. -
tesgoe about 8 yearsI added the extension, but that hasn't helped so far. Btw. I am using this code stackoverflow.com/questions/30953070/… -- from the @dharmesh-kheni 's answer.
-
tesgoe about 8 yearsBtw. I am using this code stackoverflow.com/questions/30953070/… -- from the @dharmesh-kheni 's answer.
-
Ketan Parmar about 8 yearstry to save image like this
saveImage(tempImage, path: fileInDocumentsDirectory("tempImage.png"))
from that answer. -
tesgoe about 8 yearsI'm doing exactly that now and it still does not work.
-
Ketan Parmar about 8 yearsIt should work!! strange if not work!! once try to change different name like
abc.png
insteadtempImage.png
-
tesgoe about 8 yearsloadImageFromPath(fileInDocumentsDirectory("abc.png")) returns null when saveImage(tempImage, path: fileInDocumentsDirectory("abc.png")) used.
-
tesgoe about 8 yearsThis is how it looks like from my perspective !!!save: file:///var/mobile/Applications/AE7C3783-C25C-4C4A-8ABB-650400CB32A7/Documents/abc.png !!!miss: file:///var/mobile/Applications/AE7C3783-C25C-4C4A-8ABB-650400CB32A7/Documents/abc.png
-
Duncan C about 8 yearsThat's just not true. You can certainly create a directory inside the sandboxed Documents directory and save your images there, but you don't have to do so. It works just fine to save image directly into the Documents directory.
-
tesgoe about 8 years@DuncanC Thank you. Good to know that, but it currently works for me. I had a problem without this.
-
uplearned.com over 5 yearsWorks for **Swift 4.2 ** as well! :)
-
iOS Developer over 5 yearswhat to do with
let success
? how can i store or insert or would you give an example to save on a button click and press on other button should show in image view -
Michael almost 5 yearsYou should add comments or a description of what is going on in your answer
-
ayan chakraborty almost 4 yearshe means to load & retrive from locally