Часть моего приложения имеет браузер фотографий, несколько похожий на приложение Apple's Photos, с начальным контроллером просмотра для просмотра миниатюр фотографий и подробного представления, которое отображается при нажатии на фотографию.ALAssetsLibrary - авария после получения ALAssetsLibraryChangedNotification
Я использую ALAssetsLibrary для доступа к фотографиям, и я передаю массив URL-адресов ALAsset на мой контроллер подробного представления, чтобы вы могли прокручивать с одной фотографии на другую.
Все прекрасно работает, пока не получит ALAssetsLibraryChangedNotification в то время как ударяя от одной фотографии к другой (в контроллере представления подробно), что часто приводит к аварии:
УВЕДОМЛЕНИЕ: библиотека активов изменилась // мой собственный NSLog когда уведомление происходит
загрузки активов ... // моя NSLog, когда я начинал перезагружаться активов в браузер миниатюр
Assertion не удалось: (размер == 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 объекты ... но как я должен иметь дело с ситуацией, когда он аннулирует что-то прямо в середине пытается получить к нему доступ?
Я попытался установить логическое значение, право при получении уведомления, чтобы полностью прекратить и предотвратить [currentRep метаданные] из когда-либо называется, но даже это не поймать его каждый раз:
if (self.receivedLibraryChangeNotification) {
NSLog(@"received library change notification, need to abort");
}
else {
metaDictionary = [currentRep metadata];
}
Is что я могу сделать? На этом этапе я почти готов отказаться от использования структуры ALAssetsLibrary.
(обратите внимание на эту неразрешенную нить на Девых форумах Apple, описывающих один и тот же вопрос: https://devforums.apple.com/message/604430)
Я должен сделать больше испытаний ... но это, возможно, помогло. Это не показано в моем коде выше (так как я хотел упростить его для публикации здесь), но [текущийRep метаданных] вызывается в фоновом потоке. Я изменил это, чтобы вместо этого найти словарь метаданных внутри «resultForURL» resultBlock, как вы предполагали, который находится в основном потоке. Он пока не разбился ... возможно, метод метаданных ALAssetRepresentation не является потокобезопасным? –
Самое главное здесь, что для получения средств массовой информации требуется время «assetForURL». Поэтому за пределами блока завершения вы не можете быть уверены, что у вас загружен медиа ... – voromax
Я обновил свой вопрос, чтобы точно показать, как я называл метод «метаданных» в фоновом потоке. Основываясь на вашем ответе, я изменил его, чтобы сначала получить словарь метаданных, а затем передать и это, и свой актив в мой метод configureDetailView. Опять же, мне нужно сделать больше тестов, но пока так хорошо ... –