web-dev-qa-db-ja.com

Photos FrameworkのrequestImageDataForAssetが失敗することがある

私はiOS8.1で写真フレームワークを使用しており、requestImageDataForAssetを使用してアセットの画像データをリクエストしています...ほとんどの場合それは機能し、画像データと以下に表示される内容を含む辞書を取得します。しかし、呼び出しが完了することもありますが、データはnilであり、ディクショナリには3つの一般的なエントリが含まれています。

呼び出しは順番に、同じスレッドで実行されます。特定の画像に固有のものではありません。このエラーは、過去に正常に開いた画像で発生します。誰かがこれに遭遇しましたか?

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

配列を反復処理している可能性が高く、メモリが適時に解放されていません。以下のコードを試すことができます。 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];
    }];
}
2
gabbler

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.5にアップグレードした後、iCloud共有アルバムのアセットのみを含む特定のデバイスで問題が突然発生し始めました。多分requestImageDataForAssetが(情報ディクショナリのPHImageFileURLKeyキーから)/var/mobile/Media/PhotoData/PhotoCloudSharingData/にローカルにキャッシュされたファイルを使用しようとしていて、キャッシュが壊れている可能性があると思って、そのキャッシュをクリアする方法について考えました。

IOSの「iCloud写真共有」スイッチの切り替え設定->アカウントとパスワード-> iCloud->写真でうまくいったようです。 requestImageDataForAssetは、以前は失敗していたアセットで機能するようになりました。

2018年3月9日更新

この問題を再現できます。 iTunesからバックアップを復元した後に発生するようです:

  1. IOSアプリを使用して、iCloud共有アルバムから写真を取得します。
  2. ITunesを使用してiOSデバイスをバックアップします。
  3. ITunesを使用してバックアップを復元します。
  4. アプリを再度使用してiCloud共有アルバムから同じ写真を取得すると、上記のコンソールメッセージで失敗するようになりました。

「iCloud写真共有」スイッチを切り替えると、まだ修正されます。おそらく復元プロセスが何らかのキャッシュを破壊しています。バグ38290463としてAppleに報告しました。

5
user2067021

次のコードが役立つかもしれません。 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);
0
Allan hou

久しぶりにこれに戻り、問題の大部分を解決しました。謎はなく、ただ悪いコード:

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がデフォルトの情報オブジェクトを返すことでした。

0
Dan Loughney