Можно ли заставить NSFetchedResultsController удалить объект, если одно из свойств объекта не соответствует его предикату?
У меня есть NSFetchedResultsController
-backed UICollectionViewController
, который заполнен списком объектов. Каждый объект имеет свойство BOOL, называемое deleted. Мой контроллер выборки использует следующий предикат для фильтрации моих объектов.
[NSPredicate predicateWithFormat:@"deleted == NO"];
Моя проблема заключается в том, что когда я удаляю объект, помечая его как deleted = @YES
. Последующий метод didChangeObject:
сообщает мне, что объект был обновлен и нет исключено . И объект не удаляется из представления коллекции. Если я закройте и перезагрузите моем приложении объект не отображается в представлении коллекции, что является правильным поведением.
NSFetchedResultsController
?
Обновление по запросу вот код:
Конфигурация контроллера выборки:
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"deleted == %@", @NO];
NSSortDescriptor *timestampSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"timestamp" ascending:NO];
NSSortDescriptor *prioritySortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"priority" ascending:NO];
NSManagedObjectContext *managedObjectContext = [NSManagedObjectContext MR_defaultContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:[GYNotification description] inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
[request setIncludesSubentities:YES];
[request setSortDescriptors:sortDescriptors];
[request setPredicate:predicate];
NSFetchedResultsController *aFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:request
managedObjectContext:managedObjectContext
sectionNameKeyPath:sectionNameKeyPath
cacheName:nil];
Тогда методы делегата контроллера выборки:
- (void)controller:(NSFetchedResultsController *)controller
didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath
forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath {
NSMutableDictionary *change = [NSMutableDictionary new];
switch(type) {
case NSFetchedResultsChangeInsert:
change[@(type)] = newIndexPath;
break;
case NSFetchedResultsChangeDelete:
change[@(type)] = indexPath;
break;
case NSFetchedResultsChangeUpdate:
change[@(type)] = indexPath;
break;
case NSFetchedResultsChangeMove:
change[@(type)] = @[indexPath, newIndexPath];
break;
}
[_objectChanges addObject:change];
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
if ([_objectChanges count] > 0) {
[self.collectionView performBatchUpdates:^{
for (NSDictionary *change in _objectChanges) {
[change enumerateKeysAndObjectsUsingBlock:^(NSNumber *key, id obj, BOOL *stop) {
NSFetchedResultsChangeType type = [key unsignedIntegerValue];
switch (type)
{
case NSFetchedResultsChangeInsert:
[self.collectionView insertItemsAtIndexPaths:@[obj]];
break;
case NSFetchedResultsChangeDelete:
[self.collectionView deleteItemsAtIndexPaths:@[obj]];
break;
case NSFetchedResultsChangeUpdate:
[self.collectionView reloadItemsAtIndexPaths:@[obj]];
break;
case NSFetchedResultsChangeMove:
[self.collectionView moveItemAtIndexPath:obj[0] toIndexPath:obj[1]];
break;
}
}];
}
} completion:nil];
}
[_objectChanges removeAllObjects];
}
2 ответа:
Это поведение похоже на то, что я ожидал бы от
NSFetchedResultsController
. На самом деле вы просто делаете обновление для одного из ваших объектов. Тот факт, что он названdeleted
, не имеет никакого значения. На самом деле, называть егоdeleted
немного опасно, на мой взгляд, посколькуNSManagedObject
уже имеет методisDeleted
.Похоже, что вы хотите скрыть определенные управляемые объекты из поля зрения, не удаляя их на самом деле. Я бы предложил переименовать это свойство
deleted
в нечто вродеshouldBeVisible
илиmarkedForDeletion
. Таким образом, намерение является немного яснее, и не будет такой путаницы, в каком состоянии находится ваш объект на самом деле.