Фото Framework requestImageDataForAsset иногда не работает

Я использую фреймворк photos на iOS8.1 и запрашиваю данные изображения для этого ресурса с помощью requestImageDataForAsset... В большинстве случаев он работает, и я получаю данные изображения и словарь, содержащий то, что вы видите ниже. Но иногда вызов завершается, но данные равны нулю, а словарь содержит три генерирующих элемента.

Вызовы выполняются последовательно и в одном потоке. Это не относится к какому-либо конкретному изображению. Ошибка будет происходить на изображениях, которые я успешно открыл в прошлом. Кто-нибудь сталкивался с этим?

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

Ответы

Ответ 1

Вероятно, вы итерации через массив, и память не освобождается своевременно, вы можете попробовать приведенный ниже код. Убедитесь, что 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

У меня была проблема с похожими симптомами, когда 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

В моем случае проблема внезапно начала возникать на определенном устройстве только с активами в общих альбомах iCloud после обновления с iOS 10.x до 11.0.3 и с тех пор до 11.2.5. Подумав, что, возможно, requestImageDataForAsset пытается использовать файлы, локально кэшированные в /var/mobile/Media/PhotoData/PhotoCloudSharingData/ (из информационного словаря ключ PHImageFileURLKey) и что кэш может быть поврежден, я подумал, как очистить этот кеш.

Переключение переключателя "iCloud Photo Sharing" в iOS "Настройки" → "Учетные записи и пароли" → "iCloud" → Фотографии, похоже, сделали свое дело. requestImageDataForAsset теперь работает для этих ранее requestImageDataForAsset активов.

Обновление 9 марта 2018

Я могу воспроизвести эту проблему сейчас. Кажется, это происходит после восстановления резервной копии из iTunes:

  1. Используйте приложение iOS и извлекайте фотографии из общего альбома iCloud.
  2. Сделайте резервную копию устройства iOS с помощью iTunes.
  3. Восстановите резервную копию с помощью iTunes.
  4. Повторное использование приложения для извлечения тех же фотографий из общего альбома iCloud теперь завершается неудачно с указанным выше сообщением консоли.

Переключатель "iCloud Photo Sharing" все еще исправляет это. Предположительно процесс восстановления как-то повреждает какой-то кеш. Я сообщил об этом как ошибка 38290463 в Apple.

Ответ 3

Возвращаясь к этому через долгое время, я решил большую часть своей проблемы. Нет тайны, просто плохой код:

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];
    ...
}

Наиболее распространенной причиной для меня была проблема с URL-адресом медиафайла, переданным в fetchAssetsWithALAssetURLs, заставляя объект быть nil и requestImageDataForAsset возвращать объект информации по умолчанию.