请求 PHAsset 的图像数据时 PHImageManager 的奇怪行为

Strange Behavior with PHImageManager when request Image Data for a PHAsset

我正在创建一个基本的图像编辑器,它可以拍摄图像并应用基本的元数据更改。应用任何编辑后,我使用 PHAssetChangeRequest 将编辑提交到照片库。

我的理解是,这样做并不是在修改原始媒体,而是在创建一个新的 PHAssetResource

我可以确认我的编辑工作正常,新的 PHAssetResources 正在添加到 PHAsset。请参阅下面的日志。

为什么当我请求此资产的图像数据时(在修改发生后)即使在使用 options.version = .current 请求时我也会得到原始资产。

关闭应用程序并重新启动它似乎可以纠正此行为,并且功能完全相同 returns 从那时起,正确的、修改后的图像数据。通过这样做,应用程序会完全重新加载照片库中的所有资产。但这不应该影响从资产中请求实际图像数据。

有没有办法强制 isCurrent 属性 资产资源,或者我是否遗漏了什么?

 ///Loads the photos data using a completion handler
    func getPhotoData(photo: Photo, reflectingEdits: Bool = true, completionHandler: @escaping (Data?) -> ()){

        let options = PHImageRequestOptions()
        options.isNetworkAccessAllowed = true
        options.version = .original

        if(reflectingEdits){
            options.version = .current
        }

        manager.requestImageDataAndOrientation(for: photo.asset, options: options, resultHandler: {
            data, uti, orientation, info in

            print("Succesfully delivered image (\(String(describing: uti))) -> \(data?.count ?? 0) bytes")

            completionHandler(data)
        })
    }

之前

[<PHAssetResource: 0x28328eb50> {
    type: video_cmpl
    uti: com.apple.quicktime-movie
    filename: IMG_0067.MOV
    asset: 8B5B03FE-9862-4DD9-BB81-C9753FDE328B/L0/001
    locallyAvailable: YES
    fileURL: file:///var/mobile/Media/PhotoData/CPLAssets/group125/5571C124-DF27-4636-9AFC-23786A33850B.MOV
    width: 980
    height: 1308
    fileSize: 2403227
    analysisType: unavailable
    cplResourceType: OriginalVidCompl
    isCurrent: YES
}, <PHAssetResource: 0x283281dd0> {
    type: photo
    uti: public.heic
    filename: IMG_0067.HEIC
    asset: 8B5B03FE-9862-4DD9-BB81-C9753FDE328B/L0/001
    locallyAvailable: YES
    fileURL: file:///var/mobile/Media/PhotoData/CPLAssets/group125/5571C124-DF27-4636-9AFC-23786A33850B.HEIC
    width: 3024
    height: 4032
    fileSize: 1331238
    analysisType: never-download
    cplResourceType: Original
    isCurrent: YES
}]

之后


[<PHAssetResource: 0x28329d320> {
    type: adjustment
    uti: com.apple.property-list
    filename: Adjustments.plist
    asset: 8B5B03FE-9862-4DD9-BB81-C9753FDE328B/L0/001
    locallyAvailable: YES
    fileURL: file:///var/mobile/Media/PhotoData/Mutations/PhotoData/CPLAssets/group125/5571C124-DF27-4636-9AFC-23786A33850B/Adjustments/Adjustments.plist
    width: 0
    height: 0
    fileSize: 7129
    analysisType: unavailable
    cplResourceType: Unknown
    isCurrent: NO
}, <PHAssetResource: 0x28329d440> {
    type: video_cmpl
    uti: com.apple.quicktime-movie
    filename: IMG_0067.MOV
    asset: 8B5B03FE-9862-4DD9-BB81-C9753FDE328B/L0/001
    locallyAvailable: YES
    fileURL: file:///var/mobile/Media/PhotoData/CPLAssets/group125/5571C124-DF27-4636-9AFC-23786A33850B.MOV
    width: 980
    height: 1308
    fileSize: 2403227
    analysisType: unavailable
    cplResourceType: OriginalVidCompl
    isCurrent: YES
}, <PHAssetResource: 0x28329cfc0> {
    type: photo
    uti: public.heic
    filename: IMG_0067.HEIC
    asset: 8B5B03FE-9862-4DD9-BB81-C9753FDE328B/L0/001
    locallyAvailable: YES
    fileURL: file:///var/mobile/Media/PhotoData/CPLAssets/group125/5571C124-DF27-4636-9AFC-23786A33850B.HEIC
    width: 3024
    height: 4032
    fileSize: 1331238
    analysisType: never-download
    cplResourceType: Original
    isCurrent: YES
}, <PHAssetResource: 0x28329d170> {
    type: photo_full
    uti: public.jpeg
    filename: FullSizeRender.jpg
    asset: 8B5B03FE-9862-4DD9-BB81-C9753FDE328B/L0/001
    locallyAvailable: YES
    fileURL: file:///var/mobile/Media/PhotoData/Mutations/PhotoData/CPLAssets/group125/5571C124-DF27-4636-9AFC-23786A33850B/Adjustments/FullSizeRender.jpg
    width: 4032
    height: 3024
    fileSize: 2036693
    analysisType: unavailable
    cplResourceType: JPEGFull
    isCurrent: NO
}]

我通过使用 PHAssetResourceManager 手动请求适当的资源解决了这个问题。

我找不到任何文档来证明我的理论,但我的猜测是在执行 PHAssetChangeRequest 时,新的 PHAssetResource 不会立即设置为当前。或者可能有一些操作,例如 PHImageManager class 的实例化更新了哪些资源设置为当前。

我使用 PHAssetResourceManager.requestData... 检索了 PHAssetResource 以及我想要的特定 type property/properties。它不像原来的方法那么简单,这次拆分成两个不同的函数,但这意味着我不再依赖 PHImageManager 的摆布来决定要获取的相关资源。

    ///Loads the edited photos data using a completion handler
    private func getEditedPhotoData(photo: Photo, completionHandler: @escaping (Data?) -> ()){

        if let editedPhoto = PHAssetResource.assetResources(for: photo.asset).first(where: {[=10=].type == .fullSizePhoto || [=10=].type == .alternatePhoto}){
            PHAssetResourceManager.default().requestData(for: editedPhoto, options: nil, dataReceivedHandler: completionHandler, completionHandler: {
                error in

                if(error != nil){
                    completionHandler(nil)
                }
            })
        }else{
            completionHandler(nil)
        }

    }

    /// Loads the photos original data using a completion handler
    private func getOriginalPhotoData(photo: Photo, completionHandler: @escaping (Data?) -> ()){

        let options = PHImageRequestOptions()
        options.isNetworkAccessAllowed = true
        options.version = .original

        manager.requestImageDataAndOrientation(for: photo.asset, options: options, resultHandler: {
            data, uti, orientation, info in
            completionHandler(data)
        })

    }