23

文档说:

PHImageResultIsInCloudKey:一个布尔值,指示照片资产数据是存储在本地设备上还是必须从 iCloud 下载。(NSNumber) 如果是,则没有提供图像,因为资产数据必须从 iCloud 下载。要下载数据,请提交另一个请求,并为 networkAccessAllowed 选项指定 YES。

但是,当资产存储在 iCloud 照片库中时,此密钥始终为 YES,即使它已经完全下载到设备(在我的应用程序中下载它,也在照片应用程序中打开它)。

如果图像不可用,我想让用户有可能下载它(但不要自动下载,至少在没有 Wifi 时不会这样做)。

那么如何确定是否需要下载图像?

更奇怪的是:当我的结果块 requestImageForAsset:targetSize:contentMode:options:resultHandler: 被调用以获取需要下载的图像时,在交付了一个较小且降级的版本之后,我得到了最后一次调用,请求图像 == nil。

在这种情况下,降级是否,即使我没有图像并且图像仍然必须从 iCloud 下载,因为到目前为止只有照片应用程序中的一个小缩略图在本地可用。

我在具有不同 iOS 8 版本(8.1.x、8.2 beta、8.3 beta)的 iPhone 和 iPad 上对此进行了测试,行为始终相同。

在照片应用程序中打开图像后,结果处理程序的最后一次调用具有完整大小的图像,但 PHImageResultIsInCloudKey 仍然是 YES。

这是我如何请求图像的一些代码:

PHImageRequestOptions *options = [[PHImageRequestOptions alloc]init];
options.deliveryMode = PHImageRequestOptionsDeliveryModeOpportunistic;
options.networkAccessAllowed = NO;

[self.imageManager requestImageForAsset:asset targetSize:size contentMode:PHImageContentModeAspectFill options:options resultHandler:^(UIImage *requestedImage, NSDictionary *info) {
    // Checking for requestedImage and the info keys here
    // When a full sized image was loaded, the result of PHImageResultIsInCloudKey is still YES
    // When a full sized image couldn't be loaded cause it's in the cloud, isDegraded is NO and PHImageResultIsInCloudKey is YES (as always) and requestedImage is nil
}];
4

5 回答 5

15

如果您requestImageDataForAsset:使用networkAccessAllowedset to调用NO,则返回的imageData将是nil剪辑尚未从 iCloud 下载的情况。否则它将返回实际数据,即使剪辑存储在 iCloud 中。

PHImageManager *manager = [PHImageManager defaultManager];    
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
options.networkAccessAllowed = NO;
[manager
 requestImageDataForAsset:asset
 options:options
 resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
    if ([[info valueForKey:PHImageResultIsInCloudKey] boolValue]) {
    // Image is in iCloud
        if (imageData) {
            // Image is downloaded
        } else {
            // Image is not downloaded
        }
    }
 }];
于 2016-01-22T01:37:55.110 回答
13

我可以确认 PHImageResultIsInCloudKey 不可靠。对于存储在 iCloud 中的图像,即使原始图像已下载到设备,它也会返回 1。这种行为与文档相反,我建议在radar.apple.com 上报告一个错误。PhotoKit 在我看来仍然是一个非常不成熟的框架——它包含很多问题和一些奇怪的概念决定。

于 2015-02-13T12:24:46.413 回答
3

您可以使用 progressHandler 检查 PHAsset 是否来自 iCloud。

__block BOOL isPhotoInICloud = NO;
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
options.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info){

    isPhotoInICloud = YES;
    // some code to update the download progress
});
options.networkAccessAllowed = YES;
options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
options.synchronous = NO;

[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:PHImageManagerMaximumSize contentMode:PHImageContentModeAspectFit options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
// use the options to get the high quality image for only once time.
});
于 2016-11-01T01:41:43.597 回答
1

检查 PHAsset 是否仍在云中的最佳方法是尝试使用 networkAccessAllowed = NO 通过 PHImageManager 访问它,如果您没有获得图像/资产,那么您知道它仍在云中(并且它赢了'不被下载):

    + (void)checkCloudStatusForPHAsset:(PHAsset*)phAsset completion:(void (^)(BOOL isInCloud))completionBlock
{
    if (phAsset) {
        if (phAsset.mediaType == PHAssetMediaTypeVideo) {
            PHVideoRequestOptions *options = [[PHVideoRequestOptions alloc] init];
            options.version = PHVideoRequestOptionsVersionOriginal;
            options.deliveryMode = PHVideoRequestOptionsDeliveryModeHighQualityFormat;
            options.networkAccessAllowed = NO;
            [[PHImageManager defaultManager] requestAVAssetForVideo:phAsset options:options resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {
                completionBlock(asset == nil);
            }];
        }
        else if (phAsset.mediaType == PHAssetMediaTypeImage) {
            PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
            options.version = PHImageRequestOptionsVersionOriginal;
            options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
            options.resizeMode = PHImageRequestOptionsResizeModeNone;
            options.networkAccessAllowed = NO;
            [[PHImageManager defaultManager] requestImageDataForAsset:phAsset options:options resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
                completionBlock(imageData == nil);
            }];
        }
        else {
            completionBlock(NO);
        }
    }
    else {
        completionBlock(NO);
    }
}
于 2018-06-14T14:06:46.770 回答
0

以防万一有人在尝试解决 iOS 13 中的错误时偶然发现这一点。

自 iOS 8 以来,此线程中的方法已被弃用。

在 iOS 13 中,您需要改为调用此方法:

- (PHImageRequestID)requestImageDataAndOrientationForAsset:(PHAsset *)asset 
                                                   options:(PHImageRequestOptions *)options 
                                             resultHandler:(void (^)(NSData *imageData, NSString *dataUTI, CGImagePropertyOrientation orientation, NSDictionary *info))resultHandler;

https://developer.apple.com/documentation/photokit/phimagemanager/3237282-requestimagedataandorientationfo

于 2020-01-16T14:11:18.190 回答