I am getting a photo's URL using requestContentEditingInput using the PHLibrary
asset.requestContentEditingInput(with: PHContentEditingInputRequestOptions()) { (input, _) in
let url = input?.fullSizeImageURL
}
This URL prints: file:///Users/josh/Library/Developer/CoreSimulator/Devices/EE65D986-55E7-414C-A73E-D1C96FF17004/data/Media/DCIM/100APPLE/IMG_0005.JPG.
How do I retrieve this image? I've tried the following but it does not return anything:
var fileLocation = "file:///Users/josh/Library/Developer/CoreSimulator/Devices/EE65D986-55E7-414C-A73E-D1C96FF17004/data/Media/DCIM/100APPLE/IMG_0005.JPG"
let url = URL(string: fileLocation)
let asset = PHAsset.fetchAssets(withALAssetURLs: [url!], options: nil)
if let result = asset.firstObject {
//asset.firstObject does not exist
}
apparently apple will not allow the developer to access any and every photo in the user's photo library even after they have accepted photos usage. If you are using an image that hasnt been picked from the imagePicker, (i.e. choosing last image in library), you have to store the image in the document directory before you can use the document directory URL. I guess this prevents people hacking into others photo library
//Storing the image (in my case, when selecting last photo NOT via imagePicker)
let fileManager = FileManager.default
let paths = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent("image01.jpg")
let imageData = UIImageJPEGRepresentation(image!, 1.0)
fileManager.createFile(atPath: paths as String, contents: imageData, attributes: nil)
//Retrieving the image
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("image01.jpg")
if let imageRetrieved = UIImage(contentsOfFile: imageURL.path) {
//do whatever you want with this image
print(imageRetrieved)
}
}
Related
I'm using Realm and storing the file path to captured images as Strings. I want to retrieve them later for use in a tableView. Here's my code to store the path for each image:
func saveImage(imageName: String){
//create an instance of the FileManager
let fileManager = FileManager.default
//get the image path
thisImagePath = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent(imageName)
//get the image taken with camera
let image = originalCapturedImage
//get the PNG data for this image
let data = UIImagePNGRepresentation(image!)
//store it in the document directory
fileManager.createFile(atPath: thisImagePath as String, contents: data, attributes: nil)
print("Picture path at assignment \n")
print(thisImagePath as Any)
}
And here's the code to retrieve the image:
...
var paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let documentsPath = paths[0] //Get the docs directory
let filePath = URL(fileURLWithPath: documentsPath).appendingPathComponent(item.picPath).path
let image = UIImage(contentsOfFile: filePath)
print("Picture path at retrieval \n")
print(item.picPath as Any)
cell.imageWell.image = image
cell.imageWell.clipsToBounds = true
return cell
}
Here's the comparison of the file path at runtime:
Picture path at assignment
/var/mobile/Containers/Data/Application/0E9CACAD-C6B3-4F6C-B0DB-72C43AC722E1/Documents/1535219147
...
...
Picture path at retrieval
/var/mobile/Containers/Data/Application/0E9CACAD-C6B3-4F6C-B0DB-72C43AC722E1/Documents/1535219147
The paths appear identical to me, yet no image appears. I've searched all over SO, and at one point came across a mention of the use of the URL for the file path. Somehow, I lost track of that entry and haven't been able to find it again.
Any help would be greatly appreciated!
You can try with below code for writing the image to the file instead of creating file with content. try? data.write(to: URL(fileURLWithPath: documentsPath))
You can also refer below code for saving image.
class func saveImageToFileWithDirectory(_ imageData:Data, fileName:String, folderName : String? = nil) {
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true) as NSArray
let documentsDirectory = paths.object(at: 0) as! NSString
let path = documentsDirectory.appendingPathComponent(folderName) as NSString
if !FileManager.default.fileExists(atPath: path as String) {
do {
try FileManager.default.createDirectory(atPath: path as String, withIntermediateDirectories: true, attributes: nil)
} catch let error as NSError {
print(error.localizedDescription);
}
}
let imagePath = path.appendingPathComponent(fileName)
if !FileManager.default.fileExists(atPath: imagePath as String) {
try? imageData.write(to: URL(fileURLWithPath: imagePath))
} }
Code for retrieving the image looks good. If you need help in that also, pls comment, I will post that also.
Hope this solves your issue.
I have Image cache mechanism in my app. I also need to show local notifications with images. I have a problem. When I try to set UNNotificationAttachment with an image, I get an image from my cache or, if an image doesn't exist, I download it and cache. Then I build a URL to Caches directory, but when I pass this URL to UNNotificationAttachment, I get an error: NSLocalizedDescription=Invalid attachment file URL. What do I make wrong?
if let diskUrlString = UIImageView.sharedImageCache.diskUrlForImageUrl(imageUrl) {
if let diskUrl = URL(string: diskUrlString) {
do {
res = try UNNotificationAttachment(identifier: imageUrlString, url: diskUrl, options: nil)
} catch (let error) {
print("error", error)
// Invalid attachment file URL
}
}
}
func diskUrlForImageUrl(_ imageUrl: URL) -> String? {
let urlRequest = URLRequest(url: imageUrl)
return ImageCache.cacheDirectory.appending("/\(ImageCache.imageCacheKeyFromURLRequest(urlRequest))")
}
static fileprivate var cacheDirectory: String = { () -> String in
let documentsDirectory = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).first!
let res = documentsDirectory.appending("/scAvatars")
let isExist = FileManager.default.fileExists(atPath: res, isDirectory: nil)
if !isExist {
try? FileManager.default.createDirectory(atPath: res, withIntermediateDirectories: true, attributes: nil)
}
return res
}()
I have found that if I add a prefix file:///private to diskUrlString, then URL builds like expected. But I didn't still understand, how to build the url without hardcoding this prefix. So now I can use both cache and UNNotificationAttachment!
The problem here is that you are using a path, not a URL. A path is a string, like "/var/log/foo.log". A URL is semantically more complex than a path. You need a URL that describes the location of the image file on the device file system.
Build a properly constructed URL to the image file and the attachment may work. The attachment may also need a type identifier hint to tell iOS what kind of data is in the file.
You do not have to use urls. You can use image data with UNNotificationAttachment.
Here is a sample code.
let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
let imageURL = URL(fileURLWithPath: paths.first!).appendingPathComponent("\(fileName).jpg")
let image = UIImage(contentsOfFile: imageURL.path)
let imageData = image?.pngData()
if let unwrappedImageData = imageData, let attachement = try? UNNotificationAttachment(data: unwrappedImageData, options: nil) {
content.attachments = [attachement]
}
i have a bunch of images in my App's Documents Directory. i want to load one of them in an UIImage that i have in my view. this is what i do:
myImage.image = UIImage(named: "image.jpg") // the file exist but this returns nil
I also tried to init the image using:
myImage.image = UIImage(contentsOfFile: imagePath) //this also doesn't work but the path i got starts (at least in the sim) with file://
Anyone can suggest something? I'm kinda a noob in iOS programming.
Thanks
EDIT:
imagePath comes from:
func getImgPath(name: String) -> String
{
let documentsDirectory = self.getDocumentsDirectory()
let fullpath = documentsDirectory.appendingPathComponent(name)
return fullpath.absoluteString
}
This might help
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("name.png")
let image = UIImage(contentsOfFile: imageURL.path)
// Do whatever you want with the image
}
Try adding your images under Assets.xcassets. Then you'll be able to reference your image by:
UIImage(named: 'yourImageName')
You can conveniently add images with various size settings.
You can get the path of the image as fowllows:
let imagePath = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true).appendingPathComponent("image.jpg")
If this doesn't work, check if your file name is correct.
I understand that if you are downloading images from internet means, you need to convert the URL to UIImage
if let url = URL(string: "your url") {
let data = try? Data(contentsOf: url)
if let imageData = data {
if let image = UIImage(data: imageData) {
imageView.image = image
}
}
}
If i understand your question correct, this will be the answer.
Is there a way to replace an existing image file's image, that exists in the directory?
In a method I have I retrieve what I call "default" images from the app's directory. Now, the app lets the user take images with a custom camera and I want to be able to use the same retrieve method (with the default file names) but with the new images taken with the camera.
Any ideas?
Thanks!
UPDATE:
#IBAction func show(_ sender: Any) {
image.image = UIImage(named: "image.jpg")
}
#IBAction func saveImages(_ sender: Any) {
self.saveImageDocumentDirectory()
}
func saveImageDocumentDirectory() {
let fileManager = FileManager.default
let paths = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent("image.jpg")
let image = UIImage(named: "image.jpg")
print(paths)
let imageData = UIImageJPEGRepresentation(image!, 0.5)
fileManager.createFile(atPath: paths as String, contents: imageData, attributes: nil)
}
However, I don't know how to retrieve it (if that even is the correct way to save an image to an existing file).
func saveImageDocumentDirectory() {
let fileManager = FileManager.default
let paths = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent("image.png")
let image = UIImage(named: "image.png")
let imageData = UIImageJPEGRepresentation(image!, 0.5)
fileManager.createFile(atPath: paths as String, contents: imageData, attributes: nil)
}
You can use this code on swift 4 and it works when overwriting a file :)
let fileManager = FileManager.default
let path = URL(string: "your file path here")
do {
let image = UIImage(named: "sampleImage")
if let imageData = image?.jpegData(compressionQuality: 0.5) {
try imageData.write(to: path, options: Data.WritingOptions.atomic)
}
} catch {
//handle error here
}
I am saving path in Database return by UIImagepicker from Gallery
let imageURL = info[UIImagePickerControllerReferenceURL] as! NSURL
let imageName = imageURL.lastPathComponent
let documentDirectory = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first! as String
//let localPath = documentDirectory.stringByAppendingPathComponent(imageName!)
let imagePath = String("\(documentDirectory)/\(imageName!)")
where path look like
/Users/kshitijghule/Library/Developer/CoreSimulator/Devices/3AC7B500-E980-4A00-BC32-34FA3C7DDE8A/data/Containers/Data/Application/838FB5A1-4448-46C9-8BEC-2E939668B97D/Documents/asset.JPG
Now i want load this image from this path.
i used this code
let url = NSURL(string:"/Users/kshitijghule/Library/Developer/CoreSimulator/Devices/3AC7B500-E980-4A00-BC32-34FA3C7DDE8A/data/Containers/Data/Application/838FB5A1-4448-46C9-8BEC-2E939668B97D/Documents/asset.JPG")!//path from database but mention static
let imageData = NSData(contentsOfURL:url)!
cell?.petImageView.image = UIImage(data: imageData)
But i am getting crash at line
let imageData = NSData(contentsOfURL:url)!
How to fix this issue? It will work on device ?
If you are storing images in the document directory store only image name in the db
At the time of retrieval append the current document directory path with your image name like you done at save time
let documentDirectory = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first! as String
//let localPath = documentDirectory.stringByAppendingPathComponent(imageName!)
//imageName which you have stored in the db at retrieval time
let imagePath = String("\(documentDirectory)/\(imageName!)")
let url = NSURL(string:imagePath)
let imageData = NSData(contentsOfURL:url)!
as i have also this type of issue at last if found that the app number of simulator(838FB5A1-4448-46C9-8BEC-2E939668B97D) is changes which cause the issue
Hope this may solve your issue
I have answered a similar question here.You only have to save those paths to your database, and from the database path you can retrieve those images.
Save image in Document Directory taken from Gallery or Camera.
func origionalImage(origionalImage: UIImage!, editedImage: UIImage!, userInfo info: [NSObject : AnyObject]!) {
let imageData = NSData(data:UIImagePNGRepresentation(origionalImage)!)
let paths = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
let docs: String = paths[0]
let imageName = self.randomStringWithLength(6) as String
//imageName can save in sqlite to load image later
let fullPath = String("\(docs)/\(imageName).png")
print(fullPath)
let result = imageData.writeToFile(fullPath, atomically: true)
print("FILE WRITTEN SUCCESS=>:\(result)")
}
Load Image from Database
let tempDBObject = self.petListArray[indexPath.row] as! Database
cell?.petName.text = tempDBObject.Hname
//Doc Path
let documentDirectory = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first! as String
let imagePath = String("\(documentDirectory)/\(tempDBObject.Hpath!)")
if imagePath == "" {
}else{
cell?.petImageView.image = UIImage(contentsOfFile: imagePath)
}