ALAssetsLibrary - сбой после получения ALAssetsLibraryChangedNotification

В части моего приложения есть браузер фотографий, несколько похожий на приложение Apple Photos, с контроллером исходного вида для просмотра миниатюр фотографий и подробного представления, отображаемого при нажатии на фотографию.

Я использую ALAssetsLibrary для доступа к фотографиям, и я передаю массив URL-адреса ALAsset на мой контроллер подробных представлений, чтобы вы могли прокручивать с одной фотографии на другую.

Все отлично работает, пока я не получаю ALAssetsLibraryChangedNotification при прокрутке с одной фотографии на другую (в контроллере подробного представления), что часто приводит к сбою:

УВЕДОМЛЕНИЕ: библиотека активов изменилась//мой собственный NSLog, когда уведомление происходит

загрузка активов...//мой собственный NSLog для начала перезагрузки активов в браузер эскизов

Утверждение не выполнено: (размер == bytesRead), функция - [ALAssetRepresentation _imageData], файл /SourceCache/AssetsLibrary/MobileSlideShow -1373.58.1/Sources/ALAssetRepresentation.m, строка 224.

Конкретная строка кода, с которой он падает, находится в вызове [currentRep метаданных], как показано ниже:

- (void)someMethod {
        NSURL *assetURL = [self.assetURLsArray objectAtIndex:index];
        ALAsset *currentAsset;

        [self.assetsLibrary assetForURL:assetURL resultBlock:^(ALAsset *asset) {

            [self performSelectorInBackground:@selector(configureDetailViewForAsset:) withObject:asset];

            } failureBlock:^(NSError *error) {
                    NSLog(@"failed to retrieve asset: %@", error);
        }];
}

- (void)configureDetailViewForAsset:(ALAsset *)currentAsset {
    ALAssetRepresentation *currentRep = [currentAsset defaultRepresentation];

    if (currentAsset != nil) {
        // do some stuff
    }
    else {
        NSLog(@"ERROR: currentAsset is nil");
    }

    NSDictionary *metaDictionary;
    if (currentRep != nil) {
        metaDictionary = [currentRep metadata];

        // do some other stuff
    }
    else {
        NSLog(@"ERROR: currentRep is nil");
    }
}

Я понимаю, что после получения уведомления он отменяет любые ссылки на объекты ALAsset и ALAssetRepresentation... но как я должен иметь дело с ситуацией, когда он делает недействительным что-то прямо в середине попытки получить к нему доступ?

Я пробовал установить BOOL, сразу после получения уведомления, чтобы полностью прервать и предотвратить [currentRep метаданные] из когда-либо вызываемых, но даже это не поймает его каждый раз:

if (self.receivedLibraryChangeNotification) {
    NSLog(@"received library change notification, need to abort");
}
else {
    metaDictionary = [currentRep metadata];
}

Есть ли что-нибудь, что я могу сделать? На данный момент я почти готов отказаться от использования структуры ALAssetsLibrary.

(обратите внимание на этот неразрешенный поток на форумах Apple dev, описывающий ту же проблему: https://devforums.apple.com/message/604430)

Ответ 1

Кажется, проблема здесь:

[self.assetsLibrary assetForURL:nextURL 

    resultBlock:^(ALAsset *asset) {
        // You should do some stuff with asset at this scope
        ALAssetRepresentation *currentRep = [asset defaultRepresentation];
        // Assume we have a property for that
        self.assetRepresentationMetadata = [currentRep metadata];
        ...
        // assume we have a method for that
        [self updateAssetDetailsView];
    } 

    failureBlock:^(NSError *error) {
        NSLog(@"failed to retrieve asset: %@", error);
    }];

После того, как у вас есть пользовательский ресурс, лучше скопировать информацию об активах, предоставив необходимые данные для просмотра данных вашего контроллера или путем кэширования для последующего использования. Это может быть полезно для предотвращения проблем с недействительностью ALAsset. При отправке уведомления ALAssetsLibraryChangedNotification вам может потребоваться отменить контроллер детали и запросить содержимое библиотеки с самого начала.