I'm working on image picker with camera and gallery and using following code to get image captured from camera but imageurl and image name is nil.I'm testing on mobile with os version of 11.2.2.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let image = info[UIImagePickerControllerOriginalImage] as! UIImage
let imageUrl = info[UIImagePickerControllerReferenceURL] as? NSURL
let imageName = imageUrl?.lastPathComponent
let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
let photoURL = NSURL(fileURLWithPath: documentDirectory)
let localPath = photoURL.appendingPathComponent(imageName!)
if !FileManager.default.fileExists(atPath: localPath!.path) {
do {
try UIImageJPEGRepresentation(image, 1.0)?.write(to: localPath!)
print("file saved")
}catch {
print("error saving file")
}
}
else {
print("file already exists")
}
}
Use UIImagePickerControllerImageURL instead of UIImagePickerControllerReferenceURL like this:
let imageUrl = info[UIImagePickerControllerImageURL] as? NSURL
You will not get any imageUrl or imageName because you are using the camera mode and that image is still not saved in your gallery and hence no image path is created for that camera clicked pic. So they will be nil. You can only get the UIImage object info[UIImagePickerControllerOriginalImage] in this case.
If you pick the image from photo album, then you will get everyhting. You can get the url by info[UIImagePickerControllerImageURL] and you can grab the name using the last path component.
Change your imagePickerController source to photo imagePickerController.sourceType = .photoLibrary and then you will get the urls.
Related
I did everything of getting image from camera or gallery, But how to save that image in array or in realm data to display in other viewController.
How can i do it?
Program :-
//Camera to save image and display later
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
showImage.image = info[UIImagePickerController.InfoKey.originalImage]
imagePicker.dismiss(animated: true, completion: nil)
}
If you don't want to retain image in app and just want to save image to display in other view controller then you can just pass that image to other view controller.
let viewContrller = OtherViewController() //the view controller you need to pass image to
viewController.image = image //the image you need to pass to other view controller
navigationController(push: vc, animated: true)
To save image in document directory...
func saveImage(withName name: String) {
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
// create the destination file url to save your image
let fileURL = documentsDirectory.appendingPathComponent(fileName)
// get your UIImage jpeg data representation and check if the destination file url already exists
if let data = image.jpegData(compressionQuality: 1.0),
!FileManager.default.fileExists(atPath: fileURL.path) {
do {
// writes the image data to disk
try data.write(to: fileURL)
print("file saved")
} catch {
print("error saving file:", error)
}
}
}
So you can display the saved image in other view controller.
func getImageFromDocDir(named imgName: String) -> UIImage? {
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
// create the destination file url to save your image
let fileURL = documentsDirectory.appendingPathComponent(imgName)
if FileManager.default.fileExists(atPath: fileURL.path) {
do {
let imgData = try Data(contentsOf: fileURL)
return UIImage(data: imgData)
} catch {
print(error.localizedDescription)
}
}
return nil
}
You can save image as Data, let's say you have pickedImage.
let imageData = pickedImage.pngData()
save imageData to realm.
To get image
let savedImage = UIImage(data: imageData)
I'm still new in iOS development and I'm creating an app that allows to select some photos and access them quickly.
In CoreData, I store the referenceUrl of the photo instead of the photo itself. I'm able to load photos when starting the app this way.
But, before loading photos, I need to check that they still exist and cannot figure out how to check, using the referenceUrl, if a photo exists or not.
Even using the localPath does not work. It returns false all the time.
If you have any idea how I can proceed, I'll be very grateful.
Thanks.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let imageUrl = info[UIImagePickerControllerReferenceURL] as! NSURL
let imageName = imageUrl.lastPathComponent
let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
let photoURL = NSURL(fileURLWithPath: documentDirectory)
let localPath = photoURL.appendingPathComponent(imageName!)!
let localPathString = String(describing: localPath)
let fileManager = FileManager.default
if fileManager.fileExists(atPath: localPathString){
print ("Photo exists")
} else{
print ("Photo does not exist")
}
}
I found a solution, here it is.
I use imageUrl from my code above like that:
let assets = PHAsset.fetchAssets(withALAssetURLs: [imageUrl as URL], options: nil)
if assets.firstObject != nil {
//Then the image is still there
}
else{
//The image is not present anymore
}
Hope that helps.
This below code is working perfectly fine for images picked from gallery. But will not work if taken with Camera. I tried to save image into storage and read again, but I was unable to do that. So could any one help me in this? Thank you.
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
if let referenceUrl = info[UIImagePickerControllerReferenceURL] as? NSURL, image = info[UIImagePickerControllerOriginalImage] as? UIImage {
let phAsset = PHAsset.fetchAssetsWithALAssetURLs([referenceUrl], options: nil).lastObject as! PHAsset
PHImageManager.defaultManager().requestImageDataForAsset(phAsset, options: PHImageRequestOptions(), resultHandler: { (imagedata, dataUTI, orientation, info) in
if info!.keys.contains(NSString(string: "PHImageFileURLKey")) {
let path = info![NSString(string: "PHImageFileURLKey")] as! NSURL
print("path q\(path)")
self.mImageUrl = path
self.mlocalPath = path.path
self.mImageExtension = path.pathExtension
self.mImageName = path.lastPathComponent!
print("mImageName q\(self.mImageName)")
}
})
}
dismissViewControllerAnimated(true, completion: nil)
}
Swift 5+
As the previous answers sugested, the image is not stored in gallery yet and hence no imageName. You need to store it in gallery. Use the below Helper class to save and get images from FileManager.
Thanks to this Answer
class CameraImageManager {
static let shared = CameraImageManager()
public 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)
}
}
public func getImagePathFromDiskWith(fileName: String) -> URL? {
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)
return imageUrl
}
return nil
}
public 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
}
}
Now, in your imagePickerController didFinishPickingMediaWithInfo callback function, this is how you can assign a name to an image and save it.
public func imagePickerController(_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
guard let image = info[.editedImage] as? UIImage else { return }
let imageName = "RDV_" + UUID().uuidString
CameraImageManager.shared.saveImage(imageName: imageName, image: image)
print("IMAGE NAME IS: ", imageName)
}
Hope It Helps.
You can use a notification with addObserver like this
ViewController A : where you want image to be changed, add this in viewDidLoad
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.methodOfImageChange(_:)), name:"ImageChanged", object: nil)
Add this method in ViewController A
func methodOfImageChange(notification: NSNotification){
let appStatus = notification.userInfo as? Dictionary<String,AnyObject>
// appStatus contains your image in "image" key
}
Now in didFinishPickingMediaWithInfo add this
let dictionary: [String:AnyObject] = [
"image" : (info[UIImagePickerControllerOriginalImage] as? UIImage)!,
]
NSNotificationCenter.defaultCenter().postNotificationName("ImageChanged", object: self, userInfo: dictionary)
picker .dismissViewControllerAnimated(true, completion: nil)
Hope this helps
The image isn't in the gallery yet, so I don't believe you have a name.
In my app the flow (via navigation controller) is:
Selection VC (choice of Camera or Photo Library) ->
UIImagePickerController ->
Edit VC (with back navigation and action button for - among others - saving to Photo Library)
If the user chooses Camera, they take a picture and the options are "Retake" or "Use Photo". Is they choose "Use Photo", they are in the Edit VC.
If they then choose to go back to the Select VC, the image is nowhere to be found.
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.
Note:- This question is only for Swift 3.0
I am able to get the path prio to Swift 3.0
I want to get UIImage's path picked in didFinishPickingMediaWithInfo method
let imageUrl = info[UIImagePickerControllerReferenceURL] as? NSURL
let imageName = imageUrl.lastPathComponent
let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
let photoURL = NSURL(fileURLWithPath: documentDirectory)
let localPath = photoURL.appendingPathComponent(imageName!)
But this path is not pointing to my image, Even there is no any image in Documents folder.
Can anyone help me on this?
You can't access the path of the picked image directly. You need to save that in your DocumentsDirectory and then take the image back with the path.
Do this
Swift 3.x
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let image = info[UIImagePickerControllerOriginalImage] as! UIImage
let imageUrl = info[UIImagePickerControllerReferenceURL] as? NSURL
let imageName = imageUrl?.lastPathComponent
let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
let photoURL = NSURL(fileURLWithPath: documentDirectory)
let localPath = photoURL.appendingPathComponent(imageName!)
if !FileManager.default.fileExists(atPath: localPath!.path) {
do {
try UIImageJPEGRepresentation(image, 1.0)?.write(to: localPath!)
print("file saved")
}catch {
print("error saving file")
}
}
else {
print("file already exists")
}
}
Also note that you are using the name as the last path component which is same for every file. So, this will save your image in DocumentDirectory only once as it will find the path next time.
Now when you access the localPath variable and navigate to the path, you will find the image.
NOTE:
If you are using a device here, then you need to download the container of the device, show its package contents and navigate to the Documents Directory where you will find your saved image.
In SWIFT 4 U Can Try This, It's working properly.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let imgUrl = info[UIImagePickerControllerImageURL] as? URL{
let imgName = imgUrl.lastPathComponent
let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first
let localPath = documentDirectory?.appending(imgName)
let image = info[UIImagePickerControllerOriginalImage] as! UIImage
let data = UIImagePNGRepresentation(image)! as NSData
data.write(toFile: localPath!, atomically: true)
//let imageData = NSData(contentsOfFile: localPath!)!
let photoURL = URL.init(fileURLWithPath: localPath!)//NSURL(fileURLWithPath: localPath!)
print(photoURL)
}
APPDEL.window?.rootViewController?.dismiss(animated: true, completion: nil)
}