从 iOS 共享扩展中获取 PHAsset

Get PHAsset from iOS Share Extension

我正在为我的 iOS 应用开发照片共享扩展。在扩展中,我能够从 NSItemProvider 中成功检索到 UIImage 对象。

但是,我希望能够与我的容器应用程序共享图像,而不必将整个图像数据存储在我的共享用户默认设置中。有没有办法获取用户在共享扩展中选择的图像的 PHAsset(如果他们从他们的设备中选择)?

照片框架 (https://developer.apple.com/library/ios/documentation/Photos/Reference/Photos_Framework/) 的文档中有一行内容为 "This architecture makes it easy, safe, and efficient to work with the same assets from multiple threads or multiple apps and app extensions."

这句话让我觉得有一种方法可以在扩展程序和容器应用程序之间共享相同的 PHAsset,但我还没有想出任何方法来做到这一点?有办法吗?

如果图片是从照片应用分享的,您可以获得PHAsset。项目提供者会给你一个包含图像文件名的 URL,你用它来匹配 PHAsset。

/// Assets that handle through handleImageItem:completionHandler:
private var handledAssets = [PHAsset]()

/// Key is the matched asset's original file name without suffix. E.g. IMG_193
private lazy var imageAssetDictionary: [String : PHAsset] = {

    let options = PHFetchOptions()
    options.includeHiddenAssets = true

    let fetchResult = PHAsset.fetchAssetsWithOptions(options)

    var assetDictionary = [String : PHAsset]()

    for i in 0 ..< fetchResult.count {
        let asset = fetchResult[i] as! PHAsset
        let fileName = asset.valueForKey("filename") as! String
        let fileNameWithoutSuffix = fileName.componentsSeparatedByString(".").first!
        assetDictionary[fileNameWithoutSuffix] = asset
    }

    return assetDictionary
}()

...

provider.loadItemForTypeIdentifier(imageIdentifier, options: nil) { imageItem, _ in
    if let image = imageItem as? UIImage {
      // handle UIImage
    } else if let data = imageItem as? NSData {
      // handle NSData 
    } else if let url = imageItem as? NSURL {
         // Prefix check: image is shared from Photos app
         if let imageFilePath = imageURL.path where imageFilePath.hasPrefix("/var/mobile/Media/") {
             for component in imageFilePath.componentsSeparatedByString("/") where component.containsString("IMG_") {

        // photo: /var/mobile/Media/DCIM/101APPLE/IMG_1320.PNG
        // edited photo: /var/mobile/Media/PhotoData/Mutations/DCIM/101APPLE/IMG_1309/Adjustments/FullSizeRender.jpg

                // cut file's suffix if have, get file name like IMG_1309.
                let fileName = component.componentsSeparatedByString(".").first!
                if let asset = imageAssetDictionary[fileName] {
                    handledAssets.append(asset)
                    imageCreationDate = asset.creationDate
                }
                    break
                }
            }
    }

这仅在 NSItemProvider 为您提供格式为 URL 的情况下有效:

file:///var/mobile/Media/DCIM/100APPLE/IMG_0007.PNG

这并不总是适用于您的所有资产,但如果它 returns a URL 为:

file:///var/mobile/Media/PhotoData/OutgoingTemp/2AB79E02-C977-4B4A-AFEE-60BC1641A67F.JPG

那么 PHAsset 将永远找不到您的资产。此外,后者是您文件的副本,因此如果您碰巧有一个非常大的 image/video,iOS 将在那个 OutgoingTemp 目录中复制它。文档中没有任何地方说明何时删除它,希望能尽快。

我认为这是 Apple 在 Sharing Extensions 和 PHPhotoLibrary 框架之间留下的一个很大的差距。 Apple 应该创建一个 API 来关闭它,而且很快。