1

I'm storing images and videos in a Camera Roll album using PhotoKit, and want to allow the user to share them using UIActivityViewController. If I pass UIActivityViewController a UIImage instance, it works as expected, probably because the image data is passed in memory. However, videos need to be passed by URL because there's no video analogue to UIImage. When I pass a URL to a video, I get an error "Could not create sandbox extension". If I pass a URL to an image, I get a similar error.

Based on this, it seems as though I might be able to get around this error by exporting the assets to the Documents directory, and passing UIActivityViewController the URL to the asset in Documents. However, I've read elsewhere that the Camera Roll can serve a similar purpose, and it goes to reason that the Camera Roll would be one of the few places that can hold data for sharing between apps.

Is there a way to pass UIActivityViewController URLs to Camera Roll assets without copying them to Documents? Is there a better way to be sharing images and video that are already in Camera Roll?


Implementation Details:

I'm generating URLs for assets using this:

    func videoFor(asset: PHAsset, resultHander: @escaping (AVAsset?, AVAudioMix?, [AnyHashable : Any]?) -> Void) {
        imageManager.requestAVAsset(forVideo: asset, options: nil, resultHandler: resultHander)
    }

    func urlFor(asset: PHAsset, resultHandler: @escaping (URL?) -> Void) {
        if ( asset.mediaType == .video ) {
            videoFor(asset: asset) { (asset, audioMix, info) in
                let asset = asset as! AVURLAsset
                resultHandler(asset.url)
            }
        }

        else if ( asset.mediaType == .image ) {
            let options: PHContentEditingInputRequestOptions = PHContentEditingInputRequestOptions()
            options.canHandleAdjustmentData = {(adjustmeta: PHAdjustmentData) -> Bool in
                return true
            }
            asset.requestContentEditingInput(with: options, completionHandler: {(contentEditingInput: PHContentEditingInput?, info: [AnyHashable : Any]) -> Void in
                resultHandler(contentEditingInput!.fullSizeImageURL as URL?)
            })
        }

        else {
            resultHandler(nil)
        }
    }

Here is the full error I get in console when trying to share an image by URL:

Failed to determine whether URL /var/mobile/Media/DCIM/100APPLE/IMG_0201.JPG (n) is managed by a file provider
Could not create sandbox extension. Error: Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted" UserInfo={NSLocalizedDescription=Could not create sandbox extension of type com.apple.app-sandbox.read for URL /var/mobile/Media/DCIM/100APPLE/IMG_0201.JPG. Error: No such file or directory}

... and for a video:

Failed to determine whether URL /var/mobile/Media/DCIM/100APPLE/IMG_0202.M4V (n) is managed by a file provider
Could not create sandbox extension. Error: Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted" UserInfo={NSLocalizedDescription=Could not create sandbox extension of type com.apple.app-sandbox.read for URL /var/mobile/Media/DCIM/100APPLE/IMG_0202.M4V. Error: Operation not permitted}
Ian
  • 2,078
  • 1
  • 17
  • 27

1 Answers1

0

I was stuck on the same problem today. Here is my solution. Hope this helps or guides you to the right path.

PHImageManager.default().requestExportSession(forVideo: video, options: nil, exportPreset: AVAssetExportPresetPassthrough) { (exportSession, nil) in
    if let exportSession = exportSession {
        exportSession.outputURL = destinationURLForFile
        exportSession.outputFileType = AVFileType.m4v
        exportSession.exportAsynchronously() {
            // Load the share sheet using destinationURLForFile
        }
    }
}

What this does is export the video to the provided location destinationURLForFile (i used the Documents directory. Make sure you delete the file if its already there otherwise the export MAY not work cause it may not override the file). You can set the type based on available types. I needed m4v. Then, export async and just call the share sheet or whatever sharing mechanism you have.

  • And this fixed issues sharing directly from camera roll? Are you also able to share using Air Drop using this technique? – Ian Mar 11 '19 at 17:53
  • I have not tried sharing via airdrop. But yes, this allows sharing from camera roll. What this does is export the video from the camera roll to you documents folder (or whatever folder would be appropriate in your case) in order to get an accessible URL. Cleaning up the file post hoc is something you will have to handle (or your file manager). – Christopher Cassion Mar 13 '19 at 01:59