swift ios get file path for imageView - ios

I have already copy the file absolute path and paste in simulator browser, the image can be opened. But the fileExists is fail, i dont know why..... Can anyone help
let defaultImage = "302C3FA1-E4E1-4CD8-B6DF-2FF4E4E24C11.jpeg"
loadImage(at: defaultImage)
func fileExists(at path: String) -> Bool {
return FileManager.default.fileExists(atPath: path)
}
func loadImage(at path: String) -> UIImage? {
let tempPath = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
let imagePath = "\(tempPath)\(path.trimmingCharacters(in: .whitespacesAndNewlines))"
guard fileExists(at: imagePath) else { return nil }
guard let image = UIImage(contentsOfFile: imagePath) else { return nil }
return image
}

You need split filename and extension filename.
If you use main bundle. you can follow this code
let stringPath = Bundle.main.path(forResource: "your_filename", ofType: "txt")
let urlPath = Bundle.main.url(forResource: "your_filename", withExtension: "txt")
or you can use my code.
func readConfigFromBundle(fileExtension: String) -> TCBConfigure? {
let bundle = Bundle.main
if let resPath = bundle.resourcePath {
do {
let dirContents = try FileManager.default.contentsOfDirectory(atPath: resPath)
let filteredFiles = dirContents.filter { $0.contains(fileExtension) }
for fileName in filteredFiles {
let sourceURL = bundle.bundleURL.appendingPathComponent(fileName)
let data: NSData? = NSData.init(contentsOf: sourceURL)
if let fileData = data {
// implement your logic
}
}
} catch {
// implement when error
}
}
return nil
}

Related

Swift 3 adding an Image to Documents and Retrieving

I feel like I am missing something major as I don't receive any errors or null values, but anytime I try to retrieve my image it returns "" because it doesn't exist?
This is how I am passing the image data:
URLSession.shared.dataTask(with: url! as URL, completionHandler:{ (data, response, error) in
//if download error
if error != nil{
print(error!)
return
}
guard let imageData = UIImage(data: data!) else { return }
DispatchQueue.main.async{
self.imgPortrait.image = imageData
ImagePortrait().saveImageDocumentDirectory(image: imageData)
}
The data is displayed on imgPortrait completely fine. Here are the rest of the functions where: /\(userUID)/\(CharacterSelection.sharedInstance.getActiveCharacterName()) is optional. When it goes to retrieve the image and when it saves it I can confirm the paths are exactly the same. I feel like it's how I am saving the image with createFile, but I am unsure.
func saveImageDocumentDirectory(image: UIImage){
if let userUID = Auth.auth().currentUser?.uid{
let fileManager = FileManager.default
let paths = (getDirectoryPath() as NSString).appendingPathComponent("/\(userUID)/\(CharacterSelection.sharedInstance.getActiveCharacterName())/characterPortrait.png")
createDirectory(name: (getDirectoryPath() as NSString) as String)
let imageData = UIImagePNGRepresentation(image)
fileManager.createFile(atPath: paths as String, contents: imageData, attributes: nil)
}
}
func getDirectoryPath() -> String {
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let documentsDirectory = paths[0]
return documentsDirectory
}
func getImage() -> String{
if let userUID = Auth.auth().currentUser?.uid{
let fileManager = FileManager.default
let imagePath = (self.getDirectoryPath() as NSString).appendingPathComponent("/\(userUID)/\(CharacterSelection.sharedInstance.getActiveCharacterName())/characterPortrait.png")
if fileManager.fileExists(atPath: imagePath){
return imagePath
}else{
print("No Image")
return ""
}
}
else{
return ""
}
}
func createDirectory(name: String){
let fileManager = FileManager.default
let paths = (getDirectoryPath() as NSString).appendingPathComponent(name)
if !fileManager.fileExists(atPath: paths){
try! fileManager.createDirectory(atPath: paths, withIntermediateDirectories: true, attributes: nil)
}else{
print("Directory is already created.")
}
}
Thanks in advance!
Well after a few hours I figured it out. Looks like the directory wasn't being created. Solved it by:
func saveImageDocumentDirectory(image: UIImage){
if let userUID = Auth.auth().currentUser?.uid{
let fileURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true).appendingPathComponent("\(userUID)_\(CharacterSelection.sharedInstance.getActiveCharacterName())_characterPortrait.png")
do {
try UIImagePNGRepresentation(image)?.write(to: fileURL, options: .atomic)
} catch {
print(error)
}
}
}
func getImage() -> UIImage{
if let userUID = Auth.auth().currentUser?.uid{
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("\(userUID)_\(CharacterSelection.sharedInstance.getActiveCharacterName())_characterPortrait.png")
if let image = UIImage(contentsOfFile: imageURL.path){
return image
}
else{
print("Image isn't found.")
return UIImage(named: "default_portrait.png")!
}
}
else{
print("Image isn't found.")
return UIImage(named: "default_portrait.png")!
}
}
else{
print("Image isn't found.")
return UIImage(named: "default_portrait.png")!
}
}

SSZipArchive unzip from Url

I am using SSZipArchive to unzip files from a Url (http://www.colorado.edu/conflict/peace/download/peace.zip). For this I am using the function :
SSZipArchive.unzipFile(atPath: path, toDestination: documentsPath, progressHandler: {
Is it possible to extract files from Url using SSZipArchive ?
Is yes, how do I pass Url in atPath ?
You can't directly unzip without downloading the file from the URL.
This is how I do this,
func downLoad() {
let url : String = "http://www.colorado.edu/conflict/peace/download/peace.zip"
var localPath: NSURL?
Alamofire.download(.GET,url,
destination: { (temporaryURL, response) in
let directoryURL = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0]
let pathComponent = response.suggestedFilename
localPath = directoryURL.URLByAppendingPathComponent(pathComponent!)
return localPath!
})
.response { (request, response, _, error) in
SwiftEventBus.post("DownloadedSuccessfully", sender: localPath!)
}
}
After downloading the content, unzip it where you want to.
SwiftEventBus.onMainThread(self, name:"DownloadedSuccessfully")
{
result in
let resultStatus = result.object as! NSURL
guard let zipPath: String = resultStatus.path! as String else {
return
}
guard let unZipPath = unzipPath() else {
return
}
let success = SSZipArchive.unzipFileAtPath(zipPath, toDestination: unZipPath)
print(unZipPath)
if !success {
return
}
}
I unzipped the file and stored it in the document directory
func unzipPath() -> String? {
let path = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0]
let url = NSURL(fileURLWithPath: path)
do {
try NSFileManager.defaultManager().createDirectoryAtURL(url, withIntermediateDirectories: true, attributes: nil)
} catch {
return nil
}
if let path = url.path {
return path
}
return nil
}
From there you can access the data of the file. Here I used third party frameworks Alamofire and swiftEventBus. Hope this works for you.

Swift 3: cannot write data to plist file

I am trying to use a file called Data.plist to store some simple unstructured data, and I placed this file at the root folder of my app. To make it simple to read/write to this file, I created the following DataManager struct. It can read Data.plist file with no problem, but it cannot write data to the file. I am not sure where the problem is, could anyone spot where might be wrong?
struct DataManager {
static var shared = DataManager()
var dataFilePath: String? {
return Bundle.main.path(forResource: "Data", ofType: "plist")
}
var dict: NSMutableDictionary? {
guard let filePath = self.dataFilePath else { return nil }
return NSMutableDictionary(contentsOfFile: filePath)
}
let fileManager = FileManager.default
fileprivate init() {
guard let path = dataFilePath else { return }
guard fileManager.fileExists(atPath: path) else {
fileManager.createFile(atPath: path, contents: nil, attributes: nil) // create the file
print("created Data.plist file successfully")
return
}
}
func save(_ value: Any, for key: String) -> Bool {
guard let dict = dict else { return false }
dict.setObject(value, forKey: key as NSCopying)
dict.write(toFile: dataFilePath!, atomically: true)
// confirm
let resultDict = NSMutableDictionary(contentsOfFile: dataFilePath!)
print("saving, dict: \(resultDict)") // I can see this is working
return true
}
func delete(key: String) -> Bool {
guard let dict = dict else { return false }
dict.removeObject(forKey: key)
return true
}
func retrieve(for key: String) -> Any? {
guard let dict = dict else { return false }
return dict.object(forKey: key)
}
}
You cannot modify the files inside your app bundle. So all the files that you get with Bundle.main.path(forResource:ofType:) are readable but not writable.
If you want to modify this file you will need to copy it inside your app's document directory first.
let initialFileURL = URL(fileURLWithPath: Bundle.main.path(forResource: "Data", ofType: "plist")!)
let documentDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last!
let writableFileURL = documentDirectoryURL.appendingPathComponent("Data.plist", isDirectory: false)
do {
try FileManager.default.copyItem(at: initialFileURL, to: writableFileURL)
} catch {
print("Copying file failed with error : \(error)")
}
// You can modify the file at writableFileURL

how to load image from local path ios swift (by path)

In my app I am storing an image in local storage and I am saving the path of that image in my database. How can I load the image from that path?
Here is the code I am using in order to save the image:
let myimage : UIImage = UIImage(data: data)!
let fileManager = NSFileManager.defaultManager()
let urls = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
let documentDirectory = urls[0] as NSURL
print(documentDirectory)
let currentDate = NSDate()
let dateFormatter = NSDateFormatter()
dateFormatter.dateStyle = .NoStyle
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let convertedDate = dateFormatter.stringFromDate(currentDate)
let imageURL = documentDirectory.URLByAppendingPathComponent(convertedDate)
imageUrlPath = imageURL.absoluteString
print(imageUrlPath)
UIImageJPEGRepresentation(myimage,1.0)!.writeToFile(imageUrlPath, atomically: true)
And this is the path where my image stored
file:///var/mobile/Containers/Data/Application/B2A1EE50-D800-4BB0-B475-6C7F210C913C/Documents/2016-06-01%2021:49:32
This is how i tried to retrieve the image but it's not displaying anything.
let image : String = person?.valueForKey("image_local_path") as! String
print(person!.valueForKey("image_local_path")! as! String)
cell.img_message_music.image = UIImage(contentsOfFile: image)
Folder /B2A1EE50- ... changes every time you run application.
../Application/B2A1EE50-D800-4BB0-B475-6C7F210C913C/Documents/..
Which works for me is to store fileName and get documents folder.
Swift 5
Create getter for directory folder
var documentsUrl: URL {
return FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
}
Save image :
private func save(image: UIImage) -> String? {
let fileName = "FileName"
let fileURL = documentsUrl.appendingPathComponent(fileName)
if let imageData = image.jpegData(compressionQuality: 1.0) {
try? imageData.write(to: fileURL, options: .atomic)
return fileName // ----> Save fileName
}
print("Error saving image")
return nil
}
Load image :
private func load(fileName: String) -> UIImage? {
let fileURL = documentsUrl.appendingPathComponent(fileName)
do {
let imageData = try Data(contentsOf: fileURL)
return UIImage(data: imageData)
} catch {
print("Error loading image : \(error)")
}
return nil
}
Also you can try this.
Check if your path exist
if NSFileManager.defaultManager().fileExistsAtPath(imageUrlPath) {}
Create an URL to your path
let url = NSURL(string: imageUrlPath)
Create data to you URL
let data = NSData(contentsOfURL: url!)
Bind the url to your imageView
imageView.image = UIImage(data: data!)
Final code:
if NSFileManager.defaultManager().fileExistsAtPath(imageUrlPath) {
let url = NSURL(string: imageUrlPath)
let data = NSData(contentsOfURL: url!)
imageView.image = UIImage(data: data!)
}
This code works for me
func getImageFromDir(_ imageName: String) -> UIImage? {
if let documentsUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {
let fileURL = documentsUrl.appendingPathComponent(imageName)
do {
let imageData = try Data(contentsOf: fileURL)
return UIImage(data: imageData)
} catch {
print("Not able to load image")
}
}
return nil
}
Swift 4:
if FileManager.default.fileExists(atPath: imageUrlPath) {
let url = NSURL(string: imageUrlPath)
let data = NSData(contentsOf: url! as URL)
chapterImage.image = UIImage(data: data! as Data)
}
Replace absoluteString with path
let myimage : UIImage = UIImage(data: data)!
let fileManager = NSFileManager.defaultManager()
let urls = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
let documentDirectory = urls[0] as NSURL
print(documentDirectory)
let currentDate = NSDate()
let dateFormatter = NSDateFormatter()
dateFormatter.dateStyle = .NoStyle
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let convertedDate = dateFormatter.stringFromDate(currentDate)
let imageURL = documentDirectory.URLByAppendingPathComponent(convertedDate)
imageUrlPath = imageURL.path
print(imageUrlPath)
UIImageJPEGRepresentation(myimage,1.0)!.writeToFile(imageUrlPath, atomically: true)
This sample code may save someone some typing,
write an UIImage to disk in your own directory:
IM = UIImage, your image. for example, IM = someUIView.image or from the camera
let newPhotoFileName = randomNameString() + ".jpeg"
let imagePath = checkedImageDirectoryStringPath() + "/" + newPhotoFileName
let imData = UIImageJPEGRepresentation(IM, 0.20)
FileManager.default.createFile(atPath: imagePath, contents: imData, attributes: nil)
print("saved at filename \(newPhotoFileName)")
later to read that image ...
.. and convert it back to a UIImage as in a UIImageView
NAME = that filename, like jahgfdfs.jpg
let p = checkedImageDirectoryStringPath() + "/" + NAME
devCheckExists(fullPath: p)
var imageData: Data? = nil
do {
let u = URL(fileURLWithPath: p)
imageData = try Data(contentsOf: u)
}
catch {
print("catastrophe loading file?? \(error)")
return
}
// and then to "make that an image again"...
imageData != nil {
picture.image = UIImage(data: imageData!)
print("that seemed to work")
}
else {
print("the imageData is nil?")
}
// or for example...
Alamofire.upload(
multipartFormData: { (multipartFormData) in
multipartFormData.append(imageData!,
withName: "file", fileName: "", mimeType: "image/jpeg")
...
Here are the extremely handy functions used above...
func checkedImageDirectoryStringPath()->String {
// create/check OUR OWN IMAGE DIRECTORY for use of this app.
let paths = NSSearchPathForDirectoriesInDomains(
.documentDirectory, .userDomainMask, true)
if paths.count < 1 {
print("some sort of disaster finding the our Image Directory - giving up")
return "x"
// any return will lead to disaster, so just do that
// (it will then gracefully fail when you "try" to write etc)
}
let docDirPath: String = paths.first!
let ourDirectoryPath = docDirPath.appending("/YourCompanyName")
// so simply makes a directory called "YourCompanyName"
// which will be there for all time, for your use
var ocb: ObjCBool = true
let exists = FileManager.default.fileExists(
atPath: ourDirectoryPath, isDirectory: &ocb)
if !exists {
do {
try FileManager.default.createDirectory(
atPath: ourDirectoryPath,
withIntermediateDirectories: false,
attributes: nil)
print("we did create our Image Directory, for the first time.")
// never need to again
return ourDirectoryPath
}
catch {
print(error.localizedDescription)
print("disaster trying to make our Image Directory?")
return "x"
// any return will lead to disaster, so just do that
}
}
else {
// already exists, as usual.
return ourDirectoryPath
}
}
and
func randomNameString(length: Int = 7)->String{
enum s {
static let c = Array("abcdefghjklmnpqrstuvwxyz12345789".characters)
static let k = UInt32(c.count)
}
var result = [Character](repeating: "a", count: length)
for i in 0..<length {
let r = Int(arc4random_uniform(s.k))
result[i] = s.c[r]
}
return String(result)
}
and
func devCheckExists(fullPath: String) {
var ocb: ObjCBool = false
let itExists = FileManager.default.fileExists(atPath: fullPath, isDirectory: &ocb)
if !itExists {
// alert developer. processes will fail at next step
print("\n\nDOES NOT EXIST\n\(fullPath)\n\n")
}
}
This is working for me and I think is a fast and clean way to do it.
Swift 5.0
let fileManager = NSFileManager.defaultManager()
let urls = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
let documentDirectory = urls[0] as NSURL
print(documentDirectory)
let currentDate = NSDate()
let dateFormatter = NSDateFormatter()
dateFormatter.dateStyle = .NoStyle
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let convertedDate = dateFormatter.stringFromDate(currentDate)
let imageURL = documentDirectory.URLByAppendingPathComponent(convertedDate)
let imageData = try? Data(contentsOf: imageUrl)
let image = UIImage(data: imageData!)
Where "imageUrl" is the value of your imageURL from documents folder. And "image" is the resulting image you can use anywhere you need.
1.cell.image.sd_setShowActivityIndicatorView(true)
2.cell.image.sd_setIndicatorStyle(.gray)
3.cell.image.image = UIImage(contentsOfFile: urlString!)

Saving image and then loading it in Swift (iOS)

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
}
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
}
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
}
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
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 :)
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)")
}
}
Ashish's comment has a clue to the answer. If you read the docs on UIImage(contentsOfFile:) they say
path The path to the file. This path should include the filename
extension that identifies the type of the image data.
The imageNamed call is smart enough to try the .png and .jpg extensions, but the contentsOfFile call expects a full path including extension.
If you want to load image from server you can do like below
let url = URL(string: "http://live-wallpaper.net/iphone/img/app/i/p/iphone-4s-wallpapers-mobile-backgrounds-dark_2466f886de3472ef1fa968033f1da3e1_raw_1087fae1932cec8837695934b7eb1250_raw.jpg")
URLSession.shared.dataTask(with: url!) { (data, response, error) in
guard
let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
let data = data, error == nil
else { return }
DispatchQueue.main.async() { () -> Void in
let fileManager = FileManager.default
let paths = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent("apple.jpg")
print(paths)
fileManager.createFile(atPath: paths as String, contents: data, attributes: nil)
}}.resume()
You can actually use PHPhotoLibrary to do that.
Here is the code for saving the image and fetching the image url.
extension UIImage {
func saveToPhotoLibrary(completion: #escaping (URL?) -> Void) {
var localeId: String?
PHPhotoLibrary.shared().performChanges({
let request = PHAssetChangeRequest.creationRequestForAsset(from: self)
localeId = request.placeholderForCreatedAsset?.localIdentifier
}) { (isSaved, error) in
guard isSaved else {
debugPrint(error?.localizedDescription)
completion(nil)
return
}
guard let localeId = localeId else {
completion(nil)
return
}
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
let result = PHAsset.fetchAssets(withLocalIdentifiers: [localeId], options: fetchOptions)
guard let asset = result.firstObject else {
completion(nil)
return
}
getPHAssetURL(of: asset) { (phAssetUrl) in
completion(phAssetUrl)
}
}
}
static func getPHAssetURL(of asset: PHAsset, completionHandler : #escaping ((_ responseURL : URL?) -> Void))
{
let options: PHContentEditingInputRequestOptions = PHContentEditingInputRequestOptions()
options.canHandleAdjustmentData = {(adjustmeta: PHAdjustmentData) -> Bool in
return true
}
asset.requestContentEditingInput(with: options, completionHandler: { (contentEditingInput, info) in
completionHandler(contentEditingInput!.fullSizeImageURL)
})
}
}
You have to create a directory in the Documents directory to be able to store a file.
Swift 5
func saveImage(image: UIImage) -> Bool{
guard let data = image.jpegData(compressionQuality: 1) ?? image.pngData() 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("\(txtNom.text!).png")!)
print(directory)
print(data)
print("si se pudo")
return true
} catch {
print(error.localizedDescription)
return false
}
} // saveImage
I found the solution on StackOverFlow some time ago. I didn't remember the author
Assuming yourImage is UIImage()
let ciImage = yourImage!.ciImage
let context = CIContext()
let cgImage = context.createCGImage(ciImage!, from: ciImage!.extent)
let uiImage = UIImage(cgImage: cgImage!)
UIImageWriteToSavedPhotosAlbum(uiImage, self,
#selector(self.image(_:didFinishSavingWithError:contextInfo:)), nil)
and this function
#objc func image(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
if let error = error {
// we got back an error!
let ac = UIAlertController(title: "Save error", message: error.localizedDescription, preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .default))
present(ac, animated: true)
} else {
let ac = UIAlertController(title: "Saved!", message: "Your altered image has been saved to your photos.", preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .default))
present(ac, animated: true)
}
}

Resources