Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

didFinishPickingMediaWithInfo returns different URL in iOS 13

- (void)videoPickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<UIImagePickerControllerInfoKey,id> *)info

returns different URLs in iOS 13 and the other iOSs.

Any idea why this might be happening?

iOS 13:

file:///private/var/mobile/Containers/Data/PluginKitPlugin/0849234B-837C-43ED-BEDD-DE4F79E7CE96/tmp/trim.B8AB021D-F4B6-4E50-A93C-8B7F7FB40A1C.MOV

< iOS 13:

file:///private/var/mobile/Containers/Data/Application/5AE52A95-6A2F-49A5-8210-D70E022E9A05/tmp/5A8D81B5-FC42-4228-9514-CD998A4E7FA9.MOV

This caused me to have an error since I don’t have permissions to the PluginKitPlugin folder.

In both cases, I’m selecting a video using the imagePicker.

like image 473
Kunal Shah Avatar asked Sep 05 '19 05:09

Kunal Shah


2 Answers

I struggled with this for a few nights and finally resolved the issue.

One of the differences in use case here is that I was uploading the video to AWS S3. This happens via the S3 transfer utility in a background thread. With a bunch of experimenting and debugging, Here's what I determined.

The change is that in iOS 13, the mediaURL returned in the info[.mediaURL] parameter from the image picker controller didFinishPickingMediaWithInfo method points to a temporary folder under the "PluginKitsPlugin" directory. It seems like our app doesn't have access to this location for very long.

Example: file:///private/var/mobile/Containers/Data/PluginKitPlugin/0849234B-837C-43ED-BEDD-DE4F79E7CE96/tmp/trim.B8AB021D-F4B6-4E50-A93C-8B7F7FB40A1C.MOV

For some reason (maybe someone else knows) access to that URL is only available temporarily. Some theories here suggest that dismissing the image picker controller will de-allocate the URL thus making it invalid.

With this theory I tried to work around this 2 different ways:

  1. Don't dismiss the image picker until after the upload happens. This did not work. The background process for the S3 transfer utility was still silently dying with the "file not found" error.
  2. Pass a reference to the info dictionary and use it as close to the upload point as possible. I was uploading to AWS S3 so it's possible that the dereferencing of the info dictionary was still happening when S3 went to upload in the background.

What ended up solving the issue was copying the info[.mediaURL] to another place available in my App's temporary folder.

Here's the code I used to copy the info[.mediaURL] to my App's temporary folder.

     This function will copy a video file to a temporary location so that it remains accessbile for further handling such as an upload to S3.
     - Parameter url: This is the url of the media item.
     - Returns: Return a new URL for the local copy of the vidoe file.
     */
    func createTemporaryURLforVideoFile(url: NSURL) -> NSURL {
        /// Create the temporary directory.
        let temporaryDirectoryURL = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
        /// create a temporary file for us to copy the video to.
        let temporaryFileURL = temporaryDirectoryURL.appendingPathComponent(url.lastPathComponent ?? "")
        /// Attempt the copy.
        do {
            try FileManager().copyItem(at: url.absoluteURL!, to: temporaryFileURL)
        } catch {
            print("There was an error copying the video file to the temporary location.")
        }

        return temporaryFileURL as NSURL
    }

This code copies to the file to a temp directory like one below where your app has access during its lifecycle: file:///private/var/mobile/Containers/Data/Application/5AE52A95-6A2F-49A5-8210-D70E022E9A05/tmp/5A8D81B5-FC42-4228-9514-CD998A4E7FA9.MOV

You will notice that selecting images (info[.imageURL]) to upload will return a file in the same directory. There were no prior issues uploading images.

With that the S3 transfer utility was able to access the file in a background thread and finish the video upload to S3.

like image 172
Bumbleparrot Avatar answered Oct 23 '22 02:10

Bumbleparrot


The issue may be connected to the lifetime of the url, which is extant with the lifetime of NSDictionary<UIImagePickerControllerInfoKey,id> *)info object. If the object is deallocated, the url is invalidated. So you can keep a reference to the object or copy the media to a more permanent location. I had a similar issue after the update to iOS 13 / Xcode 11.

Note: this answer was modified to conform with the information provided by @mstorsjo, also in this thread: https://stackoverflow.com/a/58099385/3220330

like image 26
rsidique Avatar answered Oct 23 '22 02:10

rsidique