请求 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)
})
}
我正在创建一个基本的图像编辑器,它可以拍摄图像并应用基本的元数据更改。应用任何编辑后,我使用 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)
})
}