I am using ImagePicker with SwiftUI by UIImagePickerController. It can select an Image. But I want to know the original image file name also. Is there any way to do this?
I already tried this using following codes:
if let url = info[UIImagePickerController.InfoKey.imageURL] as? URL {
imagePicker.fileName = url.lastPathComponent
imagePicker.fileType = url.pathExtension
}
But above code gives the temporary image file name.
You can use the originalImage attribute if you need to access the picked UIImage:
if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
...
}
I tried but I couldn't get file name (url) from UIImage.
Following code solves the problem temporarily.
if let url = info[UIImagePickerController.InfoKey.referenceURL] as? URL {
let assets = PHAsset.fetchAssets(withALAssetURLs: [url], options: nil)
if let firstAsset = assets.firstObject,
let firstResource = PHAssetResource.assetResources(for: firstAsset).first {
imagePicker.fileName = firstResource.originalFilename
} else {
imagePicker.fileName = "IMG_random_string"
}
} else {
imagePicker.fileName = "IMG_random_string"
}
But here referenceURL and fetchAssets are depreciated. I tried with PHPickerViewController, but again couldn't find how to get selected image file name from it.
Thanks! :))
Related
My iOS app (Swift 3) needs to important images from other apps using an Action Extension. I'm using the standard Action Extension template code which works just fine for apps like iOS Mail and Photos where the image shared is a URL to a local file. But for certain apps where the image being shared is the actual image data itself, my action extension code isn't getting the image.
for item: Any in self.extensionContext!.inputItems {
let inputItem = item as! NSExtensionItem
for provider: Any in inputItem.attachments! {
let itemProvider = provider as! NSItemProvider
if itemProvider.hasItemConformingToTypeIdentifier(kUTTypeImage as String) { //we'll take any image type: gif, png, jpg, etc
// This is an image. We'll load it, then place it in our image view.
weak var weakImageView = self.imageView
itemProvider.loadItem(forTypeIdentifier: kUTTypeImage as String, options: nil, completionHandler: { (imageURL,
error) in
OperationQueue.main.addOperation {
if let strongImageView = weakImageView {
if let imageURL = imageURL as? NSURL {
strongImageView.image = UIImage(data: NSData(contentsOf: imageURL as URL)! as Data)
let imageData = NSData(contentsOf: imageURL as URL)! as Data
self.gifImageView.image = UIImage.gif(data: imageData)
let width = strongImageView.image?.size.width
let height = strongImageView.image?.size.height
.... my custom logic
}
}
For reference, I reached out to the developer for one of the apps where things aren't working and he shared this code on how he is sharing the image to the Action Extension.
//Here is the relevant code. At this point the scaledImage variable holds a UIImage.
var activityItems = Array<Any?>()
if let pngData = UIImagePNGRepresentation(scaledImage) {
activityItems.append(pngData)
} else {
activityItems.append(scaledImage)
}
//Then a little later it presents the share sheet:
let activityVC = UIActivityViewController(activityItems: activityItems,applicationActivities: [])
self.present(activityVC, animated: true, completion: nil)
Figured it out thanks to this post which explains the challenge quite well https://pspdfkit.com/blog/2017/action-extension/ . In summary, we don't know if the sharing app is giving us a URL to an existing image or just raw image data so we need to modify the out of the box action extension template code to handle both cases.
for item: Any in self.extensionContext!.inputItems {
let inputItem = item as! NSExtensionItem
for provider: Any in inputItem.attachments! {
let itemProvider = provider as! NSItemProvider
if itemProvider.hasItemConformingToTypeIdentifier(kUTTypeImage as String) { //we'll take any image type: gif, png, jpg, etc
// This is an image. We'll load it, then place it in our image view.
weak var weakImageView = self.imageView
itemProvider.loadItem(forTypeIdentifier: kUTTypeImage as String, options: nil, completionHandler: { (imageURL,
error) in
OperationQueue.main.addOperation {
if let strongImageView = weakImageView {
if let imageURL = imageURL as? NSURL {
strongImageView.image = UIImage(data: NSData(contentsOf: imageURL as URL)! as Data)
let imageData = NSData(contentsOf: imageURL as URL)! as Data
self.gifImageView.image = UIImage.gif(data: imageData)
let width = strongImageView.image?.size.width
let height = strongImageView.image?.size.height
.... my custom logic
}
else
guard let imageData = imageURL as? Data else { return } //can we cast to image data?
strongImageView_.image = UIImage(data: imageData_)
//custom logic
}
Using Swift 3 for iOS, I am able to use cinemagraphs (animated gifs) that I download through a UIWebView without any problem. I am also trying to get them to work from the iPhone library. However, there is no way that I have found to get the data representation of a GIF stored in the library.
Someone will say that "there is no such thing as an animated gif in the library", but they would be wrong. Go to a web page in Safari, long-tap on an animated gif, and save it to your library. Then send a text message to yourself and copy in that image from the library. You'll see that the animated gif is intact and works perfectly.
My problem is that I need to copy the image from the library programmatically, and I'm not sure how to do it with no specific function built for GIFs. I would like to create the equivalent of UIImagePNGRepresentation or UIImageJPEGRespresentation, except for GIF images. Alternatively, is there a way to get an image from the library as a UIImage, so I don't have to try to convert it to data?
Here's the code I am using for other image formats:
* Edited to be latest version *
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let origImage = info[UIImagePickerControllerOriginalImage] as! UIImage
let refURL : URL = info[UIImagePickerControllerReferenceURL] as! URL
var resizedImage: UIImage!
var ext: String!
ext = refURL.pathExtension
if ext == "GIF" {
resizedImage = origImage
} else {
resizedImage = resizeImage(origImage: origImage, ext: ext)
}
DispatchQueue.main.async(execute: { () -> Void in
self.photoUpdated(newImage: resizedImage)
})
picker.dismiss(animated: true, completion: nil)
}
For GIFs, I tried the following, using the SwiftGif project, which was not successful:
let url = Bundle.main.url(forResource: refURL.absoluteString, withExtension: "GIF")
let data = try! Data(contentsOf: url!)
let advTimeGif = UIImage.gifWithData(data)
let imageView = UIImageView(image: advTimeGif)
newImage = imageView.image
Anyone have any suggestions as to how I might get this to work? Thanks.
Edit:
I figured out a few more pieces of the puzzle. Specifically, I can get the image name and the local path to it.
let refURL : URL = info[UIImagePickerControllerReferenceURL] as! URL
let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first! as String
let localPath = URL(fileURLWithPath: documentDirectory).appendingPathComponent(imageName)
let image = info[UIImagePickerControllerOriginalImage] as! UIImage
Still can't figure out how to get it from there to Data.
In my app I am storing an image in local storage and I am saving the path of that image in my Realm database. And now i have problems with load this image from that path?
Thats how I save path to database:
let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory,nsUserDomainMask, true)
let dirPath = paths.first
let imageURL1 = URL(fileURLWithPath: dirPath!).appendingPathComponent("refuge1.jpg")
let med1 = Meditation()
med1.name = "Refuge"
med1.count = 0
med1.targetAmount = 111111
med1.malasStep = 108
med1.imagePath = imageURL1.path
med1.id = 1
It's straightforward that am trying to get an image from this meditation.imagePath path. I double-checked the path, image is there still am not able to set the image using this path, is there is something that am missing?
In debug mode I see this:
Meditation {
name = Refuge;
count = 0;
targetAmount = 111111;
malasStep = 108;
imagePath = /Users/macbook/Library/Developer/CoreSimulator/Devices/2E25309F-D6A9-41C3-9EF4-67203142172C/data/Containers/Data/Application/F198640B-3C72-4F9C-8173-FB00D3ABEC15/Documents/refuge1.jpg;
id = 1;}
but my variable image still nil in debug mode
// Configure the cell...
cell.nameOfMeditation.text = meditation.name
cell.countOfMeditation.text = String(meditation.count)
let image = UIImage(contentsOfFile: meditation.imagePath)
cell.imageForMeditation.image = image
return cell
I see name of meditation and sound, bot no omg.
It's not advised to save the absolute file path of a file in an iOS app (ie, everything including /Users/macbook/Library/Developer/...), in Realm or anywhere else.
For security reasons, iOS devices rename the UUID folder name between launches. This means that while the folder path was valid at the time it was saved, it won't be at a later date.
Instead, it's recommended to save just the relative path of the file (eg, its location in relation to just the Documents folder. In this case, it would be just /refuge1.jpg) and to then dynamically build the absolute path by requesting the Documents directory path as you need it.
Try this:
// Use these convenience methods if you do a lot of saving and loading
func getDocumentsURL() -> URL {
let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
return documentsURL
}
func fileInDocumentsDirectory(_ filename: String) -> String {
let fileURL = getDocumentsURL().appendingPathComponent(filename)
return fileURL.path
}
func saveRefugeOne(image: UIImage) {
// Create a file name, and then save the path in your documents with that name
let imageFileName:String = "refuge1.jpg"
let imagePath = fileInDocumentsDirectory(imageFileName!)
saveImage(image, path: imagePath)
}
func loadRefugeOne() -> UIImage? {
// Get the image back
let imageName:String = "refuge1.jpg" // Or whatever name you saved
let imagePath = fileInDocumentsDirectory(imageName)
if let loadedImage = self.loadImageFromPath(imagePath) {
return loadedImage
} else {
print("Couldn't Load: \(imageName)")
return nil
}
}
// This will be your method to save image
func saveImage(_ image: UIImage, path: String ) {
//If you want PNG use this let pngImageData = UIImagePNGRepresentation(image)
// But since you mentioned JPEG:
if let jpgData = UIImageJPEGRepresentation(image, 1.0) {
try? jpgData.write(to: URL(fileURLWithPath: path), options: [.atomic])
}
}
// This will load image from saved path. Make sure to store the path
// somewhere. This makes it easier to save images locally. You can
// save the image in the documents directory, and then just save the
// path in CoreData or something similar.
func loadImageFromPath(_ path: String) -> UIImage? {
let image = UIImage(contentsOfFile: path)
if image == nil {
print("couldn't find image at path: \(path)")
}
return image
}
Hopefully this will help. It's the method I always use, and it works like a charm when I follow my own steps right ;-)
I am trying to retrieve an image saved using:
let pngData = UIImagePNGRepresentation(image)
let finalPath = filePath() // This method just create the path to save to.
saveImage(pngData, filePath: finalPath)
Later I want to retrieve this data and set the UIImageView of a UIButton. However when I use the following code, it just displays a completely blue image.
Here is the code:
let filePath = tempCard?.frontPhoto
let imgData = UIImage(contentsOfFile: filePath!)frontPhotoButton.setImage(imgData, forState: .Normal)
frontPhotoButton.setImage(imgData, forState: .Normal)
I am not sure why this is just showing a blue button.
Edit:
I have also tried:
let filePath = tempCard?.frontPhoto
let imageData = NSData(contentsOfFile: filePath!
let image = UIImage(data: imageData!)
frontPhotoButton.setImage(image, forState: .Normal)
Same result.
For anyone else who has a problem in the future setting the background image of a UIButton. Both of the above code snippets work to retrieve the image.
The Problem was, in interface builder my button was: Type - System. When I changed Type - Custom everything worked fine.
Use this method to retrieve image from document directory of an app
func loadImageFromPath() {
dispatch_async(dispatch_get_main_queue(), {
let fileManager = NSFileManager.defaultManager()
var paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
var getImagePath = paths.stringByAppendingPathComponent("Image2.png")
if (fileManager.fileExistsAtPath(getImagePath))
{
println("FILE AVAILABLE AT \(paths)");
//Pick Image and Use accordingly
var imageis: UIImage = UIImage(contentsOfFile: getImagePath)!
let data: NSData = UIImagePNGRepresentation(imageis)
self.imgProfileView.image = UIImage(data: data)
self.imgProfileView.contentMode = UIViewContentMode.ScaleAspectFit
}
else
{
println("FILE NOT AVAILABLE");
}
});
}
I'm trying to display image to imageView from URL. I successfully done it using synchronous method in a simple project. But this application is used for online store, so I took product information and image URL from a JSON file. which I'm sure I was successfully stored all the data in a product array. But the problem I'm facing is this:
fatal error: unexpectedly found nil while unwrapping an Optional value
Here is the code.
// UnWrapping imageURL
let url:NSURL? = NSURL(string: actualCurrentProduct.imageURL)
if let actualURL = url {
let imageData = NSData(contentsOfURL: actualURL)
if let actualImageData = imageData {
self.productImageView.image = UIImage(data: actualImageData)
}
}
It highlighted in this particular code.
self.productImageView.image = UIImage(data: actualImageData)
Anybody have any idea why? Really appreciated it.
I managed to display the image successfully from URL with this code. I started the project from the scratch and for the display image part, here is my code.
let imageURL = NSURL(string: actualCurrentProduct.imageURL)
if let actualImageURL = imageURL {
let imageData = NSData(contentsOfURL: actualImageURL)
if let actualImageData = imageData {
let image = UIImage(data: actualImageData)
if let actualImage = image {
self.productImage.image = actualImage
}
}
}
Finally....