PHAssetResourceManager 的 requestData 返回多个对象

PHAssetResourceManager's requestData Returning multiple objects

我正在尝试获取 PHAssetResource 的数据值,因此我可以像这样用它制作 CGImageSource

let resources = PHAssetResource.assetResources(for: imageAsset)
let fullSizePhotoResources = resources.filter { [=10=].type == .fullSizePhoto }
let targetResource = fullSizePhotoResources[0]

let resourceManager = PHAssetResourceManager()

resourceManager.requestData(for: targetResource, options: nil, dataReceivedHandler: { (resourceData) in

                            let imageSource = CGImageSourceCreateWithData(resourceData as CFData, nil)
                            print("data: \(resourceData)")
                            handler(self.getDataFromImageSource(imageSource: imageSource))

                        }) { (inError) in

                            if inError != nil {
                                //handle error
                            }
                        }

但是,我没有返回一个数据对象,而是收到了三个。所以打印语句打印这个:

data: 1048576 bytes
data: 972120 bytes
data: 0 bytes

我不确定这三个对象是什么,但只有第一个对象会产生我想要的 CGImageSource。问题是当我收到第一个对象时我无法停止请求,所以它一遍又一遍地调用处理程序。我尝试在 getDataFromImageSource 中调用 cancelDataRequest 方法,但收到一条错误消息,指出数据未完全加载。有什么想法吗?

来自 documentation for requestData:

While reading (or downloading) asset resource data, Photos calls your handler block at least once, progressively providing chunks of data. After reading all of the data, Photos calls your completionHandler block to indicate that the data is complete. (At this point, the complete data for the asset is the concatenation of the data parameters from all calls to your handler block.) If Photos cannot finish reading or downloading asset resource data, it calls your completionHandler block with a description of the error. Photos can also call the completionHandler block with a non-nil error when the data is complete if the user cancels downloading.

因此您需要从每次闭包调用中构建数据,然后在完成处理程序中您可以使用该完整数据执行某些操作。

var imageData = Data()
resourceManager.requestData(for: targetResource, options: nil, dataReceivedHandler: { (resourceData) in
    imageData.append(resourceData)
}) { (inError) in
    if let error = inError {
        //handle error
    } else {
        let imageSource = CGImageSourceCreateWithData(imageData as CFData, nil)
        print("data: \(resourceData)")
        handler(self.getDataFromImageSource(imageSource: imageSource))
    }
}