使用 UIActivityViewController 共享存储在相机胶卷中的 PHAsset

Posted

技术标签:

【中文标题】使用 UIActivityViewController 共享存储在相机胶卷中的 PHAsset【英文标题】:Share PHAsset stored in camera roll using UIActivityViewController 【发布时间】:2019-03-07 17:47:28 【问题描述】:

我正在使用 PhotoKit 将图像和视频存储在相机胶卷相册中,并希望允许用户使用 UIActivityViewController 共享它们。如果我将 UIActivityViewController 传递给 UIImage 实例,它会按预期工作,可能是因为图像数据是在内存中传递的。但是,视频需要通过 URL 传递,因为没有与 UIImage 类似的视频。当我将 URL 传递给视频时,我收到错误“无法创建沙盒扩展”。如果我将 URL 传递给图像,我会收到类似的错误。

基于this,似乎我可以通过将资产导出到 Documents 目录并将 UIActivityViewController 的 URL 传递给 Documents 中的资产来解决此错误。但是,我在其他地方读到相机胶卷可以起到类似的作用,因此相机胶卷将是少数可以保存应用程序之间共享数据的地方之一。

有没有办法将 UIActivityViewController URL 传递给相机胶卷资产而不将它们复制到文档?有没有更好的方法来分享相机胶卷中已有的图像和视频?


实现细节:

我正在使用这个为资产生成 URL:

    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)
        
    

这是我在尝试通过 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

...对于视频:

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

【问题讨论】:

【参考方案1】:

我今天遇到了同样的问题。这是我的解决方案。希望这可以帮助或引导您走上正确的道路。

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
        
    

这样做是将视频导出到提供的位置destinationURLForFile(我使用了 Documents 目录。如果文件已经存在,请确保删除该文件,否则导出可能无法正常工作,因为它可能不会覆盖该文件)。 您可以根据可用类型设置类型。我需要 m4v。 然后,导出异步并调用共享表或您拥有的任何共享机制。

【讨论】:

这解决了直接从相机胶卷分享的问题?您是否也可以使用这种技术使用 Air Drop 进行分享? 我没有尝试过空投分享。但是,是的,这允许从相机胶卷共享。这样做是将视频从相机胶卷导出到您的文档文件夹(或任何适合您的情况的文件夹),以获得可访问的 URL。事后清理文件是您必须处理的事情(或您的文件管理器)。

以上是关于使用 UIActivityViewController 共享存储在相机胶卷中的 PHAsset的主要内容,如果未能解决你的问题,请参考以下文章

测试使用

第一篇 用于测试使用

在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?

今目标使用教程 今目标任务使用篇

Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)

MySQL db 在按日期排序时使用“使用位置;使用临时;使用文件排序”