How can I get the name of video file selected from Camera roll or any other album in UIImagePickerController's delegate method ?
I'm able to get the name of image but if using same in video it's returning nil.
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType];
if (![mediaType isEqualToString:(NSString *)kUTTypeMovie])
return;
mediaURl = [info objectForKey:UIImagePickerControllerMediaURL];
//NSLog(#"mediaURL %#",mediaURl);
moviePath = mediaURl.absoluteString;
// NSLog(#"moviePath %#",moviePath);
tempFilePath = [[info objectForKey:UIImagePickerControllerMediaURL] path];
NSLog(#"filepath %#",tempFilePath);
//if you want only file name
NSArray *ar = [tempFilePath componentsSeparatedByString:#"/"];
NSString *filename = [[ar lastObject] uppercaseString];
NSLog(#"filename %#",filename);
}
Let me know if you have any issues
I know this thread is super old but i thought if someone finds it, here is a working answer in swift:
func fileName(for infoDict: [String : Any]) -> String? {
guard let referenceURL = infoDict[UIImagePickerControllerReferenceURL] as? URL else { return nil }
let result = PHAsset.fetchAssets(withALAssetURLs: [referenceURL], options: nil)
guard let asset = result.firstObject else { return nil }
let firstResource = PHAssetResource.assetResources(for: asset).first
return firstResource?.originalFilename ?? asset.value(forKey: "filename") as? String
}
Swift 4 or later
Working on My Side for the captured image
Use :
imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]){
let fileName = FileInfo.getMediaName(info: info)
}
class : pleas put the method info[:]
class FileInfo {
// Return Media name
static func getMediaName(info:[String : Any]) -> String {
if let asset = info[UIImagePickerControllerPHAsset] as? PHAsset {
let assetResources = PHAssetResource.assetResources(for: asset)
let firstObj = assetResources.first?.originalFilename as! NSString
print(firstObj)
return firstObj
}
}
}
// IMG_02256.jpeg
Related
I can load normal images: public.image types.
The Apple proRaw(adobe raw image type: DNG format) can be used in iPhone 12 series.
So, I captured with RAW image and I want to load the DNG file from app.
But I can't load the image using PHPicker.
Normally, the codes below.
PHPickerConfiguration *configuration = [[PHPickerConfiguration alloc] init];
configuration.filter = [PHPickerFilter anyFilterMatchingSubfilters:#[[PHPickerFilter imagesFilter], [PHPickerFilter livePhotosFilter]]];
PHPickerViewController *pickerController = [[PHPickerViewController alloc] initWithConfiguration:configuration];
pickerController.delegate = self;
[pickerController setModalPresentationStyle:UIModalPresentationCustom];
[pickerController setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
[viewController presentViewController:pickerController animated:YES completion:nil];
-(void)picker:(PHPickerViewController *)picker didFinishPicking:(NSArray<PHPickerResult *> *)results API_AVAILABLE(ios(14)) {
[picker dismissViewControllerAnimated:YES completion:nil];
PHPickerResult *result = [results firstObject];
if ([result.itemProvider canLoadObjectOfClass:[UIImage class]]) { // 1
[result.itemProvider loadObjectOfClass:[NSObject class] completionHandler:^(__kindof id<NSItemProviderReading> _Nullable object, NSError * _Nullable error) {
if ([object isKindOfClass:[UIImage class]]) {
UIImage *image = object;
...
}
}];
}
In comment 1 line, returned NO.
How to load raw image using PHPicker?
Using loadFileRepresentation to get the photo's data into a CGImage object worked for me. Something like:
result.itemProvider.loadFileRepresentation(forTypeIdentifier: "public.image") { url, _ in
guard let url = url,
let data = NSData(contentsOf: url),
let source = CGImageSourceCreateWithData(data, nil),
let cgImage = CGImageSourceCreateImageAtIndex(source, 0, nil) else {
// handle
}
let image = UIImage(cgImage)
...
}
or
[result.itemProvider loadFileRepresentationForTypeIdentifier:#"public.image" completionHandler:^(NSURL * _Nullable url, NSError * _Nullable error) {
if (url) {
NSData *data = [NSData dataWithContentsOfURL:url];
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
CGImageRef cgImage = CGImageSourceCreateImageAtIndex(source, 0, NULL);
UIImage *image = [UIImage imageWithCGImage:cgImage];
...
}
}];
You may need to get the correct orientation using CGImageSourceCopyPropertiesAtIndex to get the metadata dictionary, find the correct value with the kCGImagePropertyOrientation key, transform it from CGImagePropertyOrientation to UIImage.Orientation, and pass it to the UIImage initializer.
It's a bit more involved than just using loadObjectOfClass but it won't require photo access authorization.
You can use this code also. for opening new PHPicker.
For More Knowledge about PHPicker in WWDC21 PHPicker WWDC20 Video and PHPicker WWDC21 Video
WWDC PHPicker Notes PHPicker Notes
import Photos
import PhotosUI
// MARK: - PHPicker Configurations (PHPickerViewControllerDelegate)
extension ViewController: PHPickerViewControllerDelegate {
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
picker.dismiss(animated: true, completion: .none)
results.forEach { result in
result.itemProvider.loadObject(ofClass: UIImage.self) { reading, error in
guard let image = reading as? UIImage, error == nil else { return }
DispatchQueue.main.async {
self.profilePictureOutlet.image = image
// TODO: - Here you get UIImage
}
result.itemProvider.loadFileRepresentation(forTypeIdentifier: "public.image") { [weak self] url, _ in
// TODO: - Here You Get The URL
}
}
}
}
/// call this method for `PHPicker`
func openPHPicker() {
var phPickerConfig = PHPickerConfiguration(photoLibrary: .shared())
phPickerConfig.selectionLimit = 1
phPickerConfig.filter = PHPickerFilter.any(of: [.images, .livePhotos])
let phPickerVC = PHPickerViewController(configuration: phPickerConfig)
phPickerVC.delegate = self
present(phPickerVC, animated: true)
}
}
I am tring to get PHAsset from UIImagePickerController and using following code:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// NSURL *imageURL = [info valueForKey:UIImagePickerControllerReferenceURL];
PHAsset *phAsset = [info valueForKey:UIImagePickerControllerPHAsset];
if (phAsset) {
[assetsArr addObject:phAsset];
[galleryArr addObject:[info valueForKey:UIImagePickerControllerOriginalImage]];
}
dispatch_async(dispatch_get_main_queue(), ^(void) {
[self.galleryCollectionView reloadData];
[picker dismissViewControllerAnimated:YES completion:nil];
});
});
}
If source type is UIImagePickerControllerSourceTypePhotoLibrary then I am able to get PHAsset by above code. But if source type is UIImagePickerControllerSourceTypeCamera then PHAsset is nil.
How can i get PHAsset in that case?
If UIImagePickerControllerReferenceURL have some value then you can get asset using following code:
PHFetchResult<PHAsset *> *result = [PHAsset fetchAssetsWithALAssetURLs:[NSArray arrayWithObject:imageURL] options:nil];
It may have more than one asset select according to your requirement.
if you get the image from taking photo, you can get the origin image by Info Dictionary
then save the image at album
and get the PHAsset object.
the code was shown as below:
/// Save image to album.
static func saveImageToAlbum(image: UIImage, completion: ( (Bool, PHAsset?) -> Void )? ) {
let status = PHPhotoLibrary.authorizationStatus()
if status == .denied || status == .restricted {
completion?(false, nil)
return
}
var placeholderAsset: PHObjectPlaceholder? = nil
PHPhotoLibrary.shared().performChanges({
let newAssetRequest = PHAssetChangeRequest.creationRequestForAsset(from: image)
placeholderAsset = newAssetRequest.placeholderForCreatedAsset
}) { (suc, error) in
DispatchQueue.main.async {
if suc {
let asset = self.getAsset(from: placeholderAsset?.localIdentifier)
completion?(suc, asset)
} else {
completion?(false, nil)
}
}
}
}
private static func getAsset(from localIdentifier: String?) -> PHAsset? {
guard let id = localIdentifier else {
return nil
}
let result = PHAsset.fetchAssets(withLocalIdentifiers: [id], options: nil)
if result.count > 0{
return result[0]
}
return nil
}
I am using UIImagePickerController to use my camera like so:
#objc func toggle() {
if UIImagePickerController.isSourceTypeAvailable(.camera) {
//Define UIImagePickerController variable
let imagePicker = UIImagePickerController()
//Assign the delegate
imagePicker.delegate = self
//Set image picker source type
imagePicker.sourceType = .camera
//Allow Photo Editing
imagePicker.allowsEditing = true
//Present camera
UIApplication.topViewController()?.present(imagePicker, animated: true, completion: nil)
}
}
Now I am trying to capture the image taken using the didFinishPickingMediaWithInfo method, I got this example online:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let imageUrl = info[UIImagePickerControllerOriginalImage] as! NSURL
let imageName = imageUrl.lastPathComponent
let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
let photoURL = NSURL(fileURLWithPath: documentDirectory)
let localPath = photoURL.appendingPathComponent(imageName!)
let image = info[UIImagePickerControllerOriginalImage]as! UIImage
let data = UIImagePNGRepresentation(image)
do
{
try data?.write(to: localPath!, options: Data.WritingOptions.atomic)
}
catch
{
// Catch exception here and act accordingly
}
UIApplication.topViewController()?.dismiss(animated: true, completion: nil);
}
But I changed UIImagePickerControllerReferenceURL to UIImagePickerControllerOriginalImage as UIImagePickerControllerReferenceURL is nil. but after I change that I get this fatal error:
Could not cast value of type 'UIImage' (0x1b6b02b58) to 'NSURL'
How do I save the image take from the camera? What am I doing wrong?
Write your code as following this will give you image.
let image = info[UIImagePickerControllerOriginalImage] as! UIImage
UIImagePickerControllerOriginalImage return image not NSURL
Write following code to get image url in iOS 11. From iOS 11 UIImagePickerControllerImageURL is available, earlier there are UIImagePickerControllerMediaURL key to get image url.
if #available(iOS 11.0, *) {
if let imageURL = info[UIImagePickerControllerImageURL] as? URL {
print(imageURL)
}
} else {
if let imageUrl = info[UIImagePickerControllerMediaURL] as? URL {
print(imageUrl)
}
}
I hope this will help you.
The one who are searching for complete method to implement for Swift 4.2+
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let pickedImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage{
imageView.image = pickedImage
}
imgPicker.dismiss(animated: true, completion: nil)
}
This will return you the original image according to new syntax
For Image URL and Media URL, Use the respective
let imgURL = info[UIImagePickerController.InfoKey.imageURL]
let mediaURL = info[UIImagePickerController.InfoKey.mediaURL]
I am trying (AND FAILING) to get the user to upload an image and then pass the image name and actual image to another controller. This worked fine on a simulator and an actual device before ios11. But now, it just works on the simulator and crashes every time on the actual device. I am using TestFlight to test this so I am unable to see the errors on the device. But I saw this and was able to create my method which looks like this:
#objc func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let chosenImage = info[UIImagePickerControllerOriginalImage] as! UIImage
if #available(iOS 9.0, *) {
let url = info[UIImagePickerControllerReferenceURL] as! URL
//let assets = PHAsset.fetchAssets(withALAssetURLs: [url], options: nil)
//imageName = PHAssetResource.assetResources(for: assets.firstObject!).first!.originalFilename
let result = PHAsset.fetchAssets(withALAssetURLs: [url], options: nil)
imageName = PHAssetResource.assetResources(for: result.firstObject!).first!.originalFilename
// let asset = result.firstObject
// if(asset == nil){
// print("asset is NIL")
// }else {
// print("asset is not NIL")
// }
// print(asset?.value(forKey: "filename"))
// iconImageName = asset?.value(forKey: "filename") as! String
print("FILENAME START")
print(iconImageName)
print("FILENAME END")
} else {
// Fallback on earlier versions
}
self.dismiss(animated: true, completion: { () -> Void in
})
}
the commented out code are other ways I tried to get the file name. Why does this work on a simulator but not on a real device? I have looked online but this seems like the right way except it is not.
PS: Long story but my device does not work when connected to my Mac, which is why I am using TestFlight.
You can get fileName from UIImagePicker easily by this way:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let imageURL = info[UIImagePickerControllerReferenceURL] as? URL {
let result = PHAsset.fetchAssets(withALAssetURLs: [imageURL], options: nil)
let asset = result.firstObject
print(asset?.value(forKey: "filename"))
}
dismiss(animated: true, completion: nil)
}
For further information, you can follow this answer: https://stackoverflow.com/a/40628457/5167909
I believe you can get the image path(and from there the filename easily) from the info dictionary:
info[UIImagePickerControllerImageURL]
Try this:
PHAsset *asset = [self assetFromDictionary:info];
if (asset) {
NSData *fileData = nil;
NSString *fileName = [self filenameForAsset:asset];
}
- (PHAsset *)assetFromDictionary:(NSDictionary *)info {
PHAsset *asset = nil;
if (#available(iOS 11.0, *)) {
NSURL *assetURL = info[UIImagePickerControllerImageURL];
if (assetURL) {
asset = [info valueForKey:UIImagePickerControllerPHAsset];
}
} else {
NSURL *assetURL = info[UIImagePickerControllerReferenceURL];
if (assetURL) {
asset = [[PHAsset fetchAssetsWithALAssetURLs:#[assetURL] options:nil] lastObject];
}
}
return asset;
}
- (NSString *)filenameForAsset:(PHAsset *)asset {
NSString *filename = #"";
if (#available(iOS 9.0, *)) {
filename = [[PHAssetResource assetResourcesForAsset:asset] firstObject].originalFilename;
} else {
filename = [asset valueForKey:#"filename"];
}
return filename;
}
I have a CameraVC class start with :
class CameraVC: UITableViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var imagePicker = UIImagePickerController()
var image = UIImage()
var videoFilePath = NSURL()
...
I have this function :
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
let mediaType:String = info[UIImagePickerControllerMediaType] as! String
print(mediaType)
if mediaType == "public.image" {
self.image = info[UIImagePickerControllerOriginalImage] as! UIImage
if self.imagePicker.sourceType == UIImagePickerControllerSourceType.Camera {
UIImageWriteToSavedPhotosAlbum(self.image, nil, nil, nil)
}
self.dismissViewControllerAnimated(true, completion: nil)
} else if mediaType == "public.movie" {
self.videoFilePath = info[UIImagePickerControllerMediaURL] as! NSURL
print(self.videoFilePath)
// THIS LINE IS NOT WORK ->
let url = NSURL(string: self.videoFilePath)
/*if self.imagePicker.sourceType == UIImagePickerControllerSourceType.Camera {
if UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(self.videoFilePath) {
UISaveVideoAtPathToSavedPhotosAlbum(self.videoFilePath, nil, nil, nil)
}
}*/
}
}
The line :
let url = NSURL(string: self.videoFilePath)
is not working and i have a red alert with "Cannot convert value of type NSURL to expected argument type String.
The line :
print(self.videoFilePath)
write in console log :
file:///private/var/mobile/Containers/Data/Application/071BCA9C-D246-4D14-9D56-34057A17079B/tmp/capture-T0x156501280.tmp.y4Ve7u/capturedvideo.MOV
Try looking at the documentation here: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/#//apple_ref/occ/instp/NSURL/absoluteString
Try let url = NSURL(string: self.videoFilePath.absoluteString)
Also you do realise that self.videoFilePath is already an NSURL...
You have a poorly named variable. self.videoFilePath isn't a path, it's a url. You're making it a URL here:
self.videoFilePath = info[UIImagePickerControllerMediaURL] as! NSURL
If you already have self.videoFilePath as NSURL, you don't have to convert it to String and then NSURL
To keep the code safer:
if let path = info[UIImagePickerControllerMediaURL] as? NSURL {
self.videoFilePath = path
let url = path
//Continue whatever you want
}