照片框架 requestImageDataForAsset 偶尔会失败
Photos Framework requestImageDataForAsset occasionally fails
我在 iOS8.1 上使用照片框架并使用 requestImageDataForAsset 请求资产的图像数据...大部分时间它都有效,我得到图像数据和包含内容的字典你看下面。但有时调用完成,但数据为零,字典包含三个通用的条目。
调用是在同一个线程上按顺序执行的。它不特定于任何特定图像。该错误将发生在我过去成功打开的图像上。有人遇到过吗?
+ (NSData *)retrieveAssetDataPhotosFramework:(NSURL *)urlMedia resolution:(CGFloat)resolution imageOrientation:(ALAssetOrientation*)imageOrientation {
__block NSData *iData = nil;
PHFetchResult *result = [PHAsset fetchAssetsWithALAssetURLs:@[urlMedia] options:nil];
PHAsset *asset = [result firstObject];
PHImageManager *imageManager = [PHImageManager defaultManager];
PHImageRequestOptions *options = [[PHImageRequestOptions alloc]init];
options.synchronous = YES;
options.version = PHImageRequestOptionsVersionCurrent;
@autoreleasepool {
[imageManager requestImageDataForAsset:asset options:options resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
iData = [imageData copy];
NSLog(@"requestImageDataForAsset returned info(%@)", info);
*imageOrientation = (ALAssetOrientation)orientation;
}];
}
assert(iData.length != 0);
return iData;
}
这是我获取图像数据和元数据字典的期望结果:
requestImageDataForAsset returned info({
PHImageFileDataKey = <PLXPCShMemData: 0x1702214a0> bufferLength=1753088 dataLength=1749524;
PHImageFileOrientationKey = 1;
PHImageFileSandboxExtensionTokenKey = "6e14948c4d0019fbb4d14cc5e021199f724f0323;00000000;00000000;000000000000001a;com.apple.app-sandbox.read;00000001;01000003;000000000009da80;/private/var/mobile/Media/DCIM/107APPLE/IMG_7258.JPG";
PHImageFileURLKey = "file:///var/mobile/Media/DCIM/107APPLE/IMG_7258.JPG";
PHImageFileUTIKey = "public.jpeg";
PHImageResultDeliveredImageFormatKey = 9999;
PHImageResultIsDegradedKey = 0;
PHImageResultIsInCloudKey = 0;
PHImageResultIsPlaceholderKey = 0;
PHImageResultWantedImageFormatKey = 9999;
})
这是我偶尔得到的。图像数据为零。词典收录的不多。
requestImageDataForAsset returned info({
PHImageResultDeliveredImageFormatKey = 9999;
PHImageResultIsDegradedKey = 0;
PHImageResultWantedImageFormatKey = 9999;
})
你可能是在遍历一个数组,内存没有及时释放,你可以试试下面的代码。确保 theData
标记为 __block
。
@autoreleasepool {
[imageManager requestImageDataForAsset:asset options:options resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
NSLog(@"requestImageDataForAsset returned info(%@)", info);
theData = [imageData copy];
}];
}
时隔很久再回到这里,我已经解决了很大一部分问题。没有神秘,只有糟糕的代码:
PHFetchResult *result = [PHAsset fetchAssetsWithALAssetURLs:@[urlMedia] options:nil];
PHAsset *asset = [result firstObject];
if (asset != nil) { // the fix
PHImageManager *imageManager = [PHImageManager defaultManager];
PHImageRequestOptions *options = [[PHImageRequestOptions alloc]init];
...
}
对我来说最常见的原因是传递给 fetchAssetsWithALAssetURLs
的媒体 URL 出现问题,导致资产为 nil 并且 requestImageDataForAsset
return 成为默认信息对象。
我遇到了类似症状的问题,其中 requestImageDataForAsset
返回了 nil 图像数据,但还伴随着这样的控制台错误消息:
[Generic] Failed to load image data for asset <PHAsset: 0x13d041940> 87CCAFDC-A0E3-4AC9-AD1C-3F57B897A52E/L0/001 mediaType=1/0, sourceType=2, (113x124), creationDate=2015-06-29 04:56:34 +0000, location=0, hidden=0, favorite=0 with format 9999
就我而言,从 iOS 10.x 升级到 11.0.3,然后升级到 11.2 后,问题突然开始出现在特定设备上,只有 iCloud 共享相册中的资产。 5.考虑到 requestImageDataForAsset
可能正在尝试使用本地缓存在 /var/mobile/Media/PhotoData/PhotoCloudSharingData/
中的文件(来自信息字典的 PHImageFileURLKey
键)并且缓存可能已损坏,我考虑了如何清除该缓存。
切换 iOS 中的 'iCloud Photo Sharing' 开关 设置 -> 帐户和密码 -> iCloud -> 照片 似乎已经成功了。 requestImageDataForAsset
现在正在为那些以前失败的资产工作。
2018 年 3 月 9 日更新
我现在可以重现这个问题了。它似乎是在从 iTunes 恢复备份后发生的:
- 使用 iOS 应用程序并从 iCloud 共享相册中检索照片。
- 使用 iTunes 备份 iOS 设备。
- 使用 iTunes 恢复备份。
- 再次使用该应用从 iCloud 共享相册检索相同的照片现在失败并显示上述控制台消息。
切换 'iCloud Photo Sharing' 开关仍然可以修复它。据推测,恢复过程以某种方式破坏了一些缓存。我已将其作为错误 38290463 报告给 Apple。
以下代码可能会有所帮助。我认为 class PHImageRequestOptions 有一个错误,所以我通过 nil ,然后修复错误。
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[[PHImageManager defaultManager] requestImageDataForAsset:asset options:nil resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
assetModel.size = imageData.length;
NSString *filename = [asset valueForKey:@"filename"];
assetModel.fileName = filename;
dispatch_semaphore_signal(sema);
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
我在 iOS8.1 上使用照片框架并使用 requestImageDataForAsset 请求资产的图像数据...大部分时间它都有效,我得到图像数据和包含内容的字典你看下面。但有时调用完成,但数据为零,字典包含三个通用的条目。
调用是在同一个线程上按顺序执行的。它不特定于任何特定图像。该错误将发生在我过去成功打开的图像上。有人遇到过吗?
+ (NSData *)retrieveAssetDataPhotosFramework:(NSURL *)urlMedia resolution:(CGFloat)resolution imageOrientation:(ALAssetOrientation*)imageOrientation {
__block NSData *iData = nil;
PHFetchResult *result = [PHAsset fetchAssetsWithALAssetURLs:@[urlMedia] options:nil];
PHAsset *asset = [result firstObject];
PHImageManager *imageManager = [PHImageManager defaultManager];
PHImageRequestOptions *options = [[PHImageRequestOptions alloc]init];
options.synchronous = YES;
options.version = PHImageRequestOptionsVersionCurrent;
@autoreleasepool {
[imageManager requestImageDataForAsset:asset options:options resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
iData = [imageData copy];
NSLog(@"requestImageDataForAsset returned info(%@)", info);
*imageOrientation = (ALAssetOrientation)orientation;
}];
}
assert(iData.length != 0);
return iData;
}
这是我获取图像数据和元数据字典的期望结果:
requestImageDataForAsset returned info({
PHImageFileDataKey = <PLXPCShMemData: 0x1702214a0> bufferLength=1753088 dataLength=1749524;
PHImageFileOrientationKey = 1;
PHImageFileSandboxExtensionTokenKey = "6e14948c4d0019fbb4d14cc5e021199f724f0323;00000000;00000000;000000000000001a;com.apple.app-sandbox.read;00000001;01000003;000000000009da80;/private/var/mobile/Media/DCIM/107APPLE/IMG_7258.JPG";
PHImageFileURLKey = "file:///var/mobile/Media/DCIM/107APPLE/IMG_7258.JPG";
PHImageFileUTIKey = "public.jpeg";
PHImageResultDeliveredImageFormatKey = 9999;
PHImageResultIsDegradedKey = 0;
PHImageResultIsInCloudKey = 0;
PHImageResultIsPlaceholderKey = 0;
PHImageResultWantedImageFormatKey = 9999;
})
这是我偶尔得到的。图像数据为零。词典收录的不多。
requestImageDataForAsset returned info({
PHImageResultDeliveredImageFormatKey = 9999;
PHImageResultIsDegradedKey = 0;
PHImageResultWantedImageFormatKey = 9999;
})
你可能是在遍历一个数组,内存没有及时释放,你可以试试下面的代码。确保 theData
标记为 __block
。
@autoreleasepool {
[imageManager requestImageDataForAsset:asset options:options resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
NSLog(@"requestImageDataForAsset returned info(%@)", info);
theData = [imageData copy];
}];
}
时隔很久再回到这里,我已经解决了很大一部分问题。没有神秘,只有糟糕的代码:
PHFetchResult *result = [PHAsset fetchAssetsWithALAssetURLs:@[urlMedia] options:nil];
PHAsset *asset = [result firstObject];
if (asset != nil) { // the fix
PHImageManager *imageManager = [PHImageManager defaultManager];
PHImageRequestOptions *options = [[PHImageRequestOptions alloc]init];
...
}
对我来说最常见的原因是传递给 fetchAssetsWithALAssetURLs
的媒体 URL 出现问题,导致资产为 nil 并且 requestImageDataForAsset
return 成为默认信息对象。
我遇到了类似症状的问题,其中 requestImageDataForAsset
返回了 nil 图像数据,但还伴随着这样的控制台错误消息:
[Generic] Failed to load image data for asset <PHAsset: 0x13d041940> 87CCAFDC-A0E3-4AC9-AD1C-3F57B897A52E/L0/001 mediaType=1/0, sourceType=2, (113x124), creationDate=2015-06-29 04:56:34 +0000, location=0, hidden=0, favorite=0 with format 9999
就我而言,从 iOS 10.x 升级到 11.0.3,然后升级到 11.2 后,问题突然开始出现在特定设备上,只有 iCloud 共享相册中的资产。 5.考虑到 requestImageDataForAsset
可能正在尝试使用本地缓存在 /var/mobile/Media/PhotoData/PhotoCloudSharingData/
中的文件(来自信息字典的 PHImageFileURLKey
键)并且缓存可能已损坏,我考虑了如何清除该缓存。
切换 iOS 中的 'iCloud Photo Sharing' 开关 设置 -> 帐户和密码 -> iCloud -> 照片 似乎已经成功了。 requestImageDataForAsset
现在正在为那些以前失败的资产工作。
2018 年 3 月 9 日更新
我现在可以重现这个问题了。它似乎是在从 iTunes 恢复备份后发生的:
- 使用 iOS 应用程序并从 iCloud 共享相册中检索照片。
- 使用 iTunes 备份 iOS 设备。
- 使用 iTunes 恢复备份。
- 再次使用该应用从 iCloud 共享相册检索相同的照片现在失败并显示上述控制台消息。
切换 'iCloud Photo Sharing' 开关仍然可以修复它。据推测,恢复过程以某种方式破坏了一些缓存。我已将其作为错误 38290463 报告给 Apple。
以下代码可能会有所帮助。我认为 class PHImageRequestOptions 有一个错误,所以我通过 nil ,然后修复错误。
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[[PHImageManager defaultManager] requestImageDataForAsset:asset options:nil resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
assetModel.size = imageData.length;
NSString *filename = [asset valueForKey:@"filename"];
assetModel.fileName = filename;
dispatch_semaphore_signal(sema);
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);