如何识别PHAsset是否未从iCloud完全下载(所以我需要再次使用options.networkAccessAllowed请求)

问题描述 投票:19回答:5

文档说:

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

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

如果图像不可用,我希望给用户下载的可能性(但不要自动进行,至少在没有Wifi的情况下不要这样做)。

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

更加好奇:当我的结果块requestImageForAsset:targetSize:contentMode:options:resultHandler:调用了需要下载的图像,在交付了较小且降级的版本后,我得到了一个最后一个请求为requestImage == nil的呼叫。

在这种情况下,降级为否,即使我没有图像,由于至今仍只能从本地使用照片应用程序中的小缩略图,因此仍必须从iCloud下载图像。

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

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

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

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
}];
ios photokit phasset
5个回答
9
投票

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


13
投票

如果在requestImageDataForAsset:设置为networkAccessAllowed的情况下调用NO,如果尚未从iCloud下载剪辑,则返回的imageData将为nil。否则,即使剪辑存储在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
        }
    }
 }];

1
投票

您可以使用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.
});

1
投票

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

    + (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);
    }
}

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

© www.soinside.com 2019 - 2024. All rights reserved.