im using the below code to load a downloaded image from disk, when the file exists I can load it as image. If it doesn't image returns as nil.
How could I modify the code to replace return nil with loading a placeholder image from my asset folder called default.png. So instead of returning nil, there is always an image return, either downloaded one that's trying to load or if it doesn't exist, my own asset image.
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
}
You can do as below -
func loadImageFromDiskWith(fileName: String) -> UIImage {
let documentDirectory = FileManager.SearchPathDirectory.documentDirectory
let userDomainMask = FileManager.SearchPathDomainMask.userDomainMask
let paths = NSSearchPathForDirectoriesInDomains(documentDirectory, userDomainMask, true)
var image = UIImage(named: "default") // Make sure there must be "default.png" in your main bundle.
if let dirPath = paths.first {
let imageUrl = URL(fileURLWithPath: dirPath).appendingPathComponent(fileName)
if FileManager.default.fileExists(atPath: imageUrl.path) { //Check here for file existence. It won't crash.
image = UIImage(contentsOfFile: imageUrl.path)
}
}
return image
}
Related
I'm working on my app and i got stuck at one point.
There is one UIIMAGEVIEW and one UPLOAD button.
So when user click UPLOAD button he get to photo gallery to select image after selecting image I'm showing that image on UIIMAGEVIEW.
So my question is:-
after showing image on UIIMAGEVIEW i want to save that image on app to show that same image on different View Controller.
In this case you can try this code snippet:
func saveImgToDocumentDirectory(image: UIImage ) {
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let fileName = "image.png" // image name for identify particular image
let fileURL = documentsDirectory.appendingPathComponent(fileName)
if let data = UIImageJPEGRepresentation(image, 1.0),!FileManager.default.fileExists(atPath: fileURL.path){
do {
try data.write(to: fileURL)
print("file saved")
} catch {
print("error saving file:", error)
}
}
}
func loadImgFromDocumentDirectory(nameOfImage : String) -> UIImage {
let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
if let dirPath = paths.first{
let imageURL = URL(fileURLWithPath: dirPath).appendingPathComponent(nameOfImage)
let image = UIImage(contentsOfFile: imageURL.path)
return image!
}
return UIImage.init(named: "default.png")!
}
Image name is a unique identifier for the image, while storing you are required to specify the image name "imageName", so it would be easy to fetch that particular image using the same name.
You can put the image in a global variable. A global variable can be used through all the app. :
var imageSelected:UIImage? // Value will be nil if no image has been set
class ViewController1 {
// Puts your image inside a global variable
image = yourImage
}
class ViewController2 {
// Uses the image that was defined inside the global variable
#IBOutlet weak var imageView: UIView!
imageView.image = imageSelected
}
I'm using Alamofire to a download file from url, I'm getting filepath, but I'm not able to track down that filepath
let mjString = "https://wallpaperstock.net/wallpapers/thumbs1/42535.jpg"
let destination: DownloadRequest.DownloadFileDestination = { _, _ in
let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
print("destinationURLForFile *********** \(documentsURL)")
let fileURL = documentsURL.appendingPathComponent("42535.jpg")
return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
}
Alamofire.download(mjString, to: destination).response { response in
// print(response)
if response.error == nil, let imagePath = response.destinationURL?.path {
let image = UIImage(contentsOfFile: imagePath)
self.mjImage.image = image
print("imagePath = \(imagePath)")
}
}
file:///var/mobile/Containers/Data/Application/4CE55219-8244-4021-B113-1BB00B8F5B10/Documents/42535.jpg
I want that file to a custom folder, if it is possible. Any help would be appreciated.
The Output what i get is,
file:///var/mobile/Containers/Data/Application/4CE55219-8244-4021-B113-1BB00B8F5B10/Documents/42535.jpg
Append Path Component
just simply change
let fileURL = documentsURL.appendingPathComponent("42535.jpg")
to
let fileURL = documentsURL.appendingPathComponent("/yourFolder/42535.jpg")
EDIT
You can load this image with this function:
func loadImageFromDocumentDirectory(nameOfImage : String, folder: String) -> UIImage {
let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
if let dirPath = paths.first{
let imageURL = URL(fileURLWithPath: dirPath).appendingPathComponent("\(folder)/\(nameOfImage)")
if FileManager.default.fileExists(atPath: (imageURL.path)) {
if let image = UIImage(contentsOfFile: imageURL.path) {
return image
}
}
}
//Load default image if img doesnt exist.
return UIImage.init(named: "something.jpg")!
}
Just simply use it like:
imageView.image = loadImageFromDocumentDirectory(nameOfImage : "42535.jpg", folder: "yourFolder")
I have a UIImage array that I'm trying to save to disk (documents directory). I've converted it to Data so it can be saved but I can't figure out the correct/best way to save that [Data] to disk.
(arrayData as NSArray).write(to: filename, atomically: false) doesn't seem right or there seems like there is some better way.
Code so far:
// Get the new UIImage
let image4 = chartView.snapShot()
// Make UIImage into Data to save
let data = UIImagePNGRepresentation(image4!)
// Add Data image to Data Array
arrayData.append(data!)
// Get Disk/Folder
let filename = getDocumentsDirectory().appendingPathComponent("images")
// This is how I'd Write Data image to Disk
// try? data?.write(to: filename)
// TODO: Write array Data images to Disk
(arrayData as NSArray).write(to: filename, atomically: false)
To save your images to the document directory, you could start by creating a function to save your image as follows. The function handles creating the image name for you and returns it.
func saveImage(image: UIImage) -> String {
let imageData = NSData(data: UIImagePNGRepresentation(image)!)
let paths = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
let docs = paths[0] as NSString
let uuid = NSUUID().uuidString + ".png"
let fullPath = docs.appendingPathComponent(uuid)
_ = imageData.write(toFile: fullPath, atomically: true)
return uuid
}
Now since you want to save an array of images, you can simply loop and call the saveImage function:
for image in images {
saveImage(image: image)
}
If you prefer to name those images yourself, you can amend the first function to the following:
func saveImage(image: UIImage, withName name: String) {
let imageData = NSData(data: UIImagePNGRepresentation(image)!)
let paths = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
let docs = paths[0] as NSString
let name = name
let fullPath = docs.appendingPathComponent(name)
_ = imageData.write(toFile: fullPath, atomically: true)
}
When you save an image as a UIImagePNGRepresentation as you are trying to do, please note that is does not save orientation for you. This means that when you attempt to retrieve the image, it might be titled to the left. You will need to redraw your image to make sure it has the right orientation as this post will explain how to save png correctly. However, if you save your image with UIImageJPEGRepresentation you will not have to worry about all that and you can simply save your image without any extra effort.
EDITED TO GIVE ARRAY OF IMAGES
To retrieve the images you have saved, you can use the following function where you pass an array of the image names and you get an array back:
func getImage(imageNames: [String]) -> [UIImage] {
var savedImages: [UIImage] = [UIImage]()
for imageName in imageNames {
if let imagePath = getFilePath(fileName: imageName) {
savedImage.append(UIImage(contentsOfFile: imagePath))
}
}
return savedImages
}
Which relies on this function to work:
func getFilePath(fileName: String) -> String? {
let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
var filePath: String?
let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
if paths.count > 0 {
let dirPath = paths[0] as NSString
filePath = dirPath.appendingPathComponent(fileName)
}
else {
filePath = nil
}
return filePath
}
You can below code to stored image into local.
let fileManager = NSFileManager.defaultManager()
let paths = (NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSString).stringByAppendingPathComponent("ImageName.png")
let image = YOUR_IMAGE_TO_STORE.
let imageData = UIImageJPEGRepresentation(image!, 0.5)
fileManager.createFileAtPath(paths as String, contents: imageData, attributes: nil)
I am going to save an image into the iphone device and read from it.
So I had written like this for this function.
/*
* save image to local device
*/
func saveImageToLocal(image: UIImage, fileName: String) {
if let data = UIImagePNGRepresentation(image) {
let filePath = self.getDocumentsDirectory().appendingPathComponent(fileName)
try? data.write(to: filePath, options: .atomic)
}
}
/*
* get image from local device
*/
func getImageFromLocal(fileName:String) -> UIImage? {
if let filePath = "\(self.getDocumentsDirectory())\(fileName)" as String! {
if let image = UIImage(contentsOfFile: filePath) {
return image
}
}
return nil
}
/*
* get document directory to save/read local file
*/
func getDocumentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentsDirectory = paths[0]
return documentsDirectory
}
But it didn't work correctly.
Which mistake do I have for this?
How can I implement this?
Regards.
You have the problem in getting filePath inside your getImageFromLocal(fileName:) -> UIImage? method. Change this according to your saveImageToLocal(image:) method as like below:
func getImageFromLocal(fileName:String) -> UIImage? {
let filePath = self.getDocumentsDirectory().appendingPathComponent(fileName)
if let image = UIImage(contentsOfFile: filePath.path) {
return image
}
return nil
}
I want to save and read a UIImage to my temp folder when my app closes and then load and delete it when the app loads. How do I accomplish this. Please help.
These methods allow you to save and retrieve an image from the documents directory on the iphone
+ (void)saveImage:(UIImage *)image withName:(NSString *)name {
NSData *data = UIImageJPEGRepresentation(image, 1.0);
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:name];
[fileManager createFileAtPath:fullPath contents:data attributes:nil];
}
+ (UIImage *)loadImage:(NSString *)name {
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:name];
UIImage *img = [UIImage imageWithContentsOfFile:fullPath];
return img;
}
Swift 3 xCode 8.2
Documents directory obtaining:
func getDocumentDirectoryPath() -> NSString {
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let documentsDirectory = paths[0]
return documentsDirectory as NSString
}
Saving:
func saveImageToDocumentsDirectory(image: UIImage, withName: String) -> String? {
if let data = UIImagePNGRepresentation(image) {
let dirPath = getDocumentDirectoryPath()
let imageFileUrl = URL(fileURLWithPath: dirPath.appendingPathComponent(withName) as String)
do {
try data.write(to: imageFileUrl)
print("Successfully saved image at path: \(imageFileUrl)")
return imageFileUrl.absoluteString
} catch {
print("Error saving image: \(error)")
}
}
return nil
}
Loading:
func loadImageFromDocumentsDirectory(imageName: String) -> UIImage? {
let tempDirPath = getDocumentDirectoryPath()
let imageFilePath = tempDirPath.appendingPathComponent(imageName)
return UIImage(contentsOfFile:imageFilePath)
}
Example:
//TODO: pass your image to the actual method call here:
let pathToSavedImage = saveImageToDocumentsDirectory(image: imageToSave, withName: "imageName.png")
if (pathToSavedImage == nil) {
print("Failed to save image")
}
let image = loadImageFromDocumentsDirectory(imageName: "imageName.png")
if image == nil {
print ("Failed to load image")
}
Swift 4 implementation:
// saves an image, if save is successful, returns its URL on local storage, otherwise returns nil
func saveImage(_ image: UIImage, name: String) -> URL? {
guard let imageData = image.jpegData(compressionQuality: 1) else {
return nil
}
do {
let imageURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent(name)
try imageData.write(to: imageURL)
return imageURL
} catch {
return nil
}
}
// returns an image if there is one with the given name, otherwise returns nil
func loadImage(withName name: String) -> UIImage? {
let imageURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent(name)
return UIImage(contentsOfFile: imageURL.path)
}
Usage example (assuming we have an image):
let image = UIImage(named: "milan")
let url = saveImage(image, name: "savedMilan.jpg")
print(">>> URL of saved image: \(url)")
let reloadedImage = loadImage(withName: "savedMilan.jpg")
print(">>> Reloaded image: \(reloadedImage)")
In addition, you don't ever want to save anything into the actual tmp directory that you want around after the app shuts down. The tmp directory can be purged by the system. By definition, it exist solely to hold minor files needed only when the app is running.
Files you want to preserve should always go into the documents directory.
Tested Code for swift
//to get document directory path
func getDocumentDirectoryPath() -> NSString {
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let documentsDirectory = paths[0]
return documentsDirectory
}
Call using
if let data = UIImagePNGRepresentation(img) {
let filename = self.getDocumentDirectoryPath().stringByAppendingPathComponent("resizeImage.png")
data.writeToFile(filename, atomically: true)
}
The Untested Swift tweak for selected answer:
class func saveImage(image: UIImage, withName name: String) {
let documentsDirectory = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as! String
var data: NSData = UIImageJPEGRepresentation(image, 1.0)!
var fileManager: NSFileManager = NSFileManager.defaultManager()
let fullPath = NSURL(fileURLWithPath: NSTemporaryDirectory()).URLByAppendingPathComponent(name)
fileManager.createFileAtPath(fullPath.absoluteString, contents: data, attributes: nil)
}
class func loadImage(name: String) -> UIImage {
var fullPath: String = NSURL(fileURLWithPath: NSTemporaryDirectory()).URLByAppendingPathComponent(name).absoluteString
var img:UIImage = UIImage(contentsOfFile: fullPath)!
return img
}