web-dev-qa-db-ja.com

PHAssetがiCloudから完全にダウンロードされていないかどうかを識別する方法(したがって、options.networkAccessAllowedで再度リクエストする必要があります)

ドキュメントによると:

PHImageResultIsInCloudKey:写真アセットデータがローカルデバイスに保存されているか、iCloudからダウンロードする必要があるかを示すブール値。 (NSNumber)YESの場合、アセットデータはiCloudからダウンロードする必要があるため、画像は提供されませんでした。データをダウンロードするには、別のリクエストを送信し、networkAccessAllowedオプションにYESを指定します。

ただし、アセットがiCloudフォトライブラリに保存されている場合、デバイスに完全にダウンロードされている場合でも、このキーは常にYESです(アプリでダウンロードし、フォトアプリで開いた場合でも)。

画像が利用できない場合は、ユーザーにダウンロードできるようにしたいです(ただし、少なくともWifiがない場合は、自動的にダウンロードしないでください)。

では、画像をダウンロードする必要があるかどうかを確認するにはどうすればよいですか?

さらに興味深いことに、ダウンロードする必要のある画像に対してrequestImageForAsset:targetSize:contentMode:options:resultHandler:の結果ブロックが呼び出されると、小さくて劣化したバージョンが配信された後、requestedImage == nilで最後の呼び出しが行われます。

この場合、劣化はNOです。画像がなく、写真アプリの小さなサムネイルしかローカルで利用できないため、画像をiCloudからダウンロードする必要があります。

私はこれを異なるiOS8バージョン(8.1.x、8.2ベータ、8.3ベータ)の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
}];
20
Thyraz

PHImageResultIsInCloudKeyが信頼できないことを確認できます。 iCloudに保存されている画像の場合、元の画像がデバイスにダウンロードされていても、1が返されます。この動作はドキュメントとは対照的であり、radar.Apple.comでバグを報告することをお勧めします。私の意見では、PhotoKitはまだ非常に未成熟なフレームワークであり、多くの問題といくつかの奇妙な概念上の決定が含まれています。

9
holtmann

networkAccessAllowedNOに設定してrequestImageDataForAsset:を呼び出すと、クリップがiCloudからまだダウンロードされていない場合、返されるimageDatanilになります。それ以外の場合、クリップが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
        }
    }
 }];
13
bcattle

PHAssetがまだクラウドにあるかどうかを確認する最良の方法は、networkAccessAllowed = NOを指定してPHImageManagerを介してアクセスすることです。画像/アセットを取得できない場合は、PHAssetがまだクラウドにあることがわかります(そして勝ちました)ダウンロードされません):

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

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
Chris Forever

IOS 13のバグを解決しようとしているときに、誰かがこれに遭遇した場合に備えて。

このスレッドのメソッドは、iOS8以降非推奨になっています。

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

0
Waxhaw