У меня есть fetchedResultsController с предикатом, где "isOpen == YES"
При вызове closeCurrentClockSet я установил для этого свойства значение НЕТ. Поэтому он больше не должен появляться на моем столе.
Для некоторых причин этого не происходит.
Может кто-нибудь помочь мне понять это, пожалуйста?
-(void)closeCurrentClockSet
{
NSPredicate * predicate = [NSPredicate predicateWithFormat:@"isOpen == YES"];
NSArray *fetchedObjects =
[self fetchRequestForEntity:@"ClockSet"
withPredicate:predicate
inManagedObjectContext:[myAppDelegate managedObjectContext]];
ClockSet *currentClockSet = (ClockSet *)fetchedObjects.lastObject;
[currentClockSet setIsOpen:[NSNumber numberWithBool:NO]];
}
-
У меня есть еще несколько методов, используя точный подход, путем вызова настраиваемого метода fetchRequestForEntity: withPredicate: inManagedObjectContext.
В этих методах при изменении свойства tableView получает корректное обновление! Но этот выше (closeCurrentClockSet), нет! Я не могу понять, почему.
-
Моя реализация для моего fetchedResultsController, из документации Apple.
Кроме того, еще одна деталь. Если я отправлю свое приложение на задний план. Закройте его и заново откройте, tableView показывает обновленный как он должен!
Я попытался изо всех сил следить за предыдущими вопросами здесь, в stackOverflow. Не повезло. Я также NSLogged это кость. Объект получает правильную выборку. Это правильный. isOpen Свойство корректно обновляется до НЕТ. Но по какой-то причине мой fetchedResultsController не обновляет tableView.
Я попробовал пару "молотковых" решений, таких как reloadData и call performFetch. Но это не сработало. Или было бы разумно использовать их...
РЕДАКТИРОВАТЬ: поцарапать, что он работает, вызывая reloadData imediatly после выполненияFetch на моем resultsController, но с использованием reloadData забивает решение. Кроме того, он извлекает все анимации. Я хочу, чтобы мой контроллер автоматически обновлял мой tableView.
Может кто-нибудь помочь мне понять это?
Любая помощь очень ценится!
Спасибо,
Нуну
EDIT:
Полная реализация.
fetchedResultsController довольно стандартный и простой. Все остальное связано с документацией Apple
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController) {
return _fetchedResultsController;
}
NSManagedObjectContext * managedObjectContext = [myAppDelegate managedObjectContext];
NSEntityDescription *entity =
[NSEntityDescription entityForName:@"ClockPair"
inManagedObjectContext:managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:entity];
NSString *predicate = [NSString stringWithFormat: @"clockSet.isOpen == YES"];
[fetchRequest setPredicate: [NSPredicate predicateWithFormat:predicate]];
NSSortDescriptor *sortDescriptor1 =
[[NSSortDescriptor alloc] initWithKey:@"clockIn" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor1, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
[fetchRequest setFetchBatchSize:20];
NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:managedObjectContext
sectionNameKeyPath:nil
cacheName:@"Root"];
_fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
-
Код котла с документацией Apple:
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
// The fetch controller is about to start sending change notifications, so prepare the table view for updates.
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller
didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath
forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
UITableView *tableView = self.tableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationTop];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationLeft];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationTop];
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller
didChangeSection:(id )sectionInfo
atIndex:(NSUInteger)sectionIndex
forChangeType:(NSFetchedResultsChangeType)type
{
UITableView *tableView = self.tableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
// The fetch controller has sent all current change notifications, so tell the table view to process all updates.
[self.tableView endUpdates];
}
1ST ОБНОВЛЕНИЕ:
Отслеживание [managedObjectContext hasChanges] возвращает ДА, как и должно быть. Но fetchedResultsController не обновляет tableView
2ND UPDATE
didChangeObject: atIndexPath: не получает вызов для этого конкретного случая! У меня есть еще два метода, с ТОЧНЫМ кодом, они просто разные. И они отлично работают. Спасибо @Leonardo за указание на это
3-й UPDATE этот метод следует тем же правилам. Но действительно работает.
- (void)clockOut
{
NSPredicate * predicate = [NSPredicate predicateWithFormat:@"isOpen == %@", [NSNumber numberWithBool:YES]];
NSArray * fetchedObjects =
[self fetchRequestForEntity:@"ClockPair"
withPredicate:predicate
inManagedObjectContext:[myAppDelegate managedObjectContext]];
ClockPair *aClockPair = (ClockPair *)fetchedObjects.lastObject;
aClockPair.clockOut = [NSDate date];
aClockPair.isOpen = [NSNumber numberWithBool:NO];
}
У кого-нибудь есть какие-то другие идеи по поводу того, что я могу потерять?
Спасибо,
Нуну