52

如何确定PHAssetiOS 设备上可用的最大图像尺寸,其中“可用”是指当前在设备上,不需要从 iCloud 照片库进行任何网络下载?

我一直在开发一个应用程序,其中一组缩略图显示在一个UICollectionView(很像照片应用程序)中,然后用户可以选择一个图像来查看它的全尺寸。如有必要,将从 iCloud 下载完整大小的图像。但是,我想向用户展示图像的最大可能版本,直到完整尺寸可用。

照片框架的工作方式相当奇怪:

在集合视图中,我使用186x186 像素(由于视网膜缩放而使尺寸加倍)PHCachingImageManager缓存(以及后来的请求)图像。targetSizeUICollectionViewCell

效果非常好,滚动速度非常快,并且在用图像填充单元格时没有延迟。检查返回图像的大小,它们都是大约 342x256 像素。那是在我的 iPhone 6 上启用了 iCloud 照片库并启用了“优化存储”,因此对于大多数图像来说,设备上只存储了小缩略图。

然而,奇怪的是,如果我随后请求任何图像的全尺寸(或更大)版本,无论是使用该选项PHCachingImageManager还是PHImageManager.defaultManager()使用该PHImageRequestOptionsDeliveryMode.Opportunistic选项,返回的第一张(低质量)图像是一个看起来很小的 60x45 像素邮票全屏显示太可怕了,直到最终下载完整尺寸的图像来替换它。

显然,设备上已经更大的缩略图 (342x256),因为它们刚刚显示在集合视图中!那么为什么在下载完整尺寸之前它不将它们作为第一个“低质量”图像返回?为了确保 342x256 图像确实已经在设备上,我在飞行模式下运行了代码,因此没有发生网络访问。

我发现,如果我请求任何最大为 256x256 的尺寸,我会返回 342x256 的图像。一旦我变大(甚至 1 像素),它首先会返回 60x45 图像,然后尝试下载完整尺寸的图像。

我已经更改了我的代码,首先发出一个 256x256 的请求,然后是一个完整尺寸的请求PHImageRequestOptionsDeliveryMode.HighQualityFormat(它不会返回一个微小的中间图像),而且效果很好。这也是 iOS 照片应用程序必须做的事情,因为它在下载完整图像时会显示相对高质量的缩略图。

那么,在这样的背景下,我怎么知道设备图像的最大尺寸是PHAsset多少?256x256 是一个神奇的数字,还是取决于 iCloud 照片库如何优化空间(基于库的大小和可用的设备存储空间)?

当然,这似乎是一个错误,照片框架没有返回当前可用的最大图像(当被要求提供比当前更大的尺寸时),并且要获得最大尺寸,您必须要求该尺寸或更小,因为如果你要求更大,你会得到一个 60x45 的缩影!奇怪。

更新:提交给 Apple 的错误报告:https
://openradar.appspot.com/25181601 演示错误的示例项目:https ://github.com/mluisbrown/PhotoKitBug

4

3 回答 3

2

使用问题中发布的示例项目,我能够在模拟器中重现该问题,但是当我进行以下更改时,我只会收到最大的图像:

let targetSize = PHImageManagerMaximumSize
于 2016-04-08T17:56:22.793 回答
0

其实我不知道苹果为什么会返回 PHImageResultIsDegradedKey=1 的降级 45*60 图像的原因。对我来说,我一开始只使用 deliveryMode PHImageRequestOptionsDeliveryModeHighQualityFormat 请求 256*256 图像,然后我使用其他 PHImageRequestOptions 请求全尺寸图像,如下所示:

PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
options.networkAccessAllowed = YES;
options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
options.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info){
// code to update the iCloud download progress
});

[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:PHImageManagerMaximumSize contentMode:PHImageContentModeAspectFit options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
// code to update UIImageView or something else.
});

而且我认为,Instagram 可能会使用这种类似的解决方案来处理来自 iCloud 的图像。

于 2016-11-01T02:11:03.443 回答
-3
[imageManager requestImageForAsset:asset
              targetSize: PHImageManagerMaximumSize
              contentMode:PHImageContentModeAspectFill
              options:nil
resultHandler:^(UIImage *result, NSDictionary *info)
{
    result;
}];
于 2016-04-16T09:41:13.590 回答