-1

I am trying to get file name from PHAsset reference provided by UIImagePickerController,How do I retrieve the image file name when choose from library and take photo with camera?

I am using Xcode 11.4 and Swift 5.

Prabhakar
  • 15
  • 1
  • 3

2 Answers2

1

Given, you already have the PHAsset object, PHAssetResource is what you need to work retrieve the filename.

let assetResources = PHAssetResource.assetResources(for: asset)

This will return you an array of PHAssetResource instances, among which one of them is the current image.

Inspecting the PHAssetResource instances on the debugger, you can see it contains multiple files. This may include adjustment data, represented by .plist, and one or more photos.

To get the file that is currently accessible, what you need to look for is a key isCurrent. Apple hasn't exposed this key as a variable for PHAssetResource, however, they don't take any effort hiding the value. And I assume, querying this value doesn't result in an app rejection.

You can query this value directly, or can do it more cleanly by extending PHAssetResource.

extension PHAssetResource {
    var isCurrent: Bool? {
        self.value(forKey: "isCurrent") as? Bool
    }
}

Now, you can ask the [PHAssetResource], for the first item that isCurrent as well as a photo or video.

let resourceTypes: [PHAssetResourceType] = [.photo, .video, .audio, .fullSizePhoto]
let currentAssetResource = assetResources.first(
   where: { $0.isCurrent == true && resourceTypes.contains($0.type)
})

And, finally for the filename.

let fileName = currentAssetResource?.originalFilename

Note

PhotoKit expects the developer to work with the abstract asset resource, and not to deal with the underlying files or data. The usage of isCurrent seems to be allowed. However, the value can be altered or removed with an iOS update. Do it only if you have a strong use-case for extracting the filename.

egghese
  • 2,193
  • 16
  • 26
0

There are two approaches:

  1. You can retrieve the URL of the temporary file that UIImagePickerController creates for you using info[.imageURL]. If you only need, for example, the extension of the asset, this is sufficient.

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
    
        // url of temporary file provided by image picker
    
        if let url = info[.imageURL] as? URL {
            print("temp URL", url)                         // file:///private/var/mobile/Containers/Data/Application/.../tmp/FAC0D82B-85A9-4C7A-B69C-58BB53F74CDC.jpeg
        }
    
        dismiss(animated: true)
    }
    

    But the filename, itself, bears no relationship to the original asset.

  2. You can retrieve the original asset URL from the Photos framework. We used to be able to use PHImageManager, call requestImageDataForAsset, and then use "PHImageFileURLKey" in the resulting info dictionary, but that doesn’t work anymore.

    But as suggested elsewhere, you can asset.requestContentEditingInput, and that includes the URL of the asset:

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
    
        // url of the original asset
    
        if let asset = info[.phAsset] as? PHAsset {
            asset.requestContentEditingInput(with: nil) { input, info in
                if let fileURL = input?.fullSizeImageURL {
                    print("original URL", fileURL)         // file:///var/mobile/Media/DCIM/100APPLE/IMG_0135.HEIC
                }
            }
        }
    
        dismiss(animated: true)
    }
    

    If you do this, you obviously need to request permissions for the photos library, notably:

    if PHPhotoLibrary.authorizationStatus() == .notDetermined {
        PHPhotoLibrary.requestAuthorization { granted in
            print(granted)
        }
    }
    

    And you need to supply a NSPhotoLibraryUsageDescription usage string in your Info.plist.

    Personally, it feels wrong to request content editing input when you don’t really need to edit, but AFAIK, that’s the only way to get the original asset name nowadays. (There’s got to be a better way: If you browse the PHAsset in the debugger, the asset name is actually buried in there, but not exposed ... maybe they did that to avoid confusion with the HEIC extension.)

Bottom line, it just depends upon what you need the name for. If you just need the path for the temporary file, then use .imageURL. If you need information about the original asset, use .phAsset and the Photos/PhotoKit framework.

Rob
  • 415,655
  • 72
  • 787
  • 1,044