NSFetchedResultsController siempre no devuelve filas

Estoy intentando get un NSFetchedResultsController funcione con mi vista de tabla, pero a pesar de mis mejores esfuerzos para configurarlo correctamente, siempre está regresando sin filas. He abierto mi almacén de datos a través de Finder y he confirmado a través de un editor SQLite que en realidad hay muchos loggings, pero siempre devuelve cero. ¿Qué me estoy perdiendo?

Custom getter para el controller:

 - (NSFetchedResultsController *)fetchedResultsController { if (fetchedResultsController_ != nil) { return fetchedResultsController_; } RBGameItemController* itemController = [RBGameItemController shanetworkingInstance]; NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"GameItem" inManagedObjectContext:itemController.managedObjectContext]; [fetchRequest setEntity:entity]; NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:NO]; [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]]; [fetchRequest setFetchBatchSize:20]; NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:itemController.managedObjectContext sectionNameKeyPath:nil cacheName:@"Root"]; self.fetchedResultsController = theFetchedResultsController; self.fetchedResultsController.delegate = self; [sort release]; [fetchRequest release]; [theFetchedResultsController release]; return self.fetchedResultsController; } 

Estoy buscando los datos en viewDidLoad :

 - (void)viewDidLoad { [super viewDidLoad]; NSError *error = nil; if (![self.fetchedResultsController performFetch:&error]) { NSLog(@"Unresolved error %@, %@", error, [error userInfo]); } } 

Delegado de resultados obtenidos:

 - (void)controllerWillChangeContent:(NSFetchedResultsController *)controller { // The fetch controller is about to start sending change notifications, so prepare the table view for updates. [self.tableView beginUpdates]; NSLog(@"controllerWillChangeContent"); } - (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath { NSLog(@"controller:didChangeObject:"); UITableView *tableView = self.tableView; switch(type) { case NSFetchedResultsChangeInsert: [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; break; case NSFetchedResultsChangeDelete: [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; break; case NSFetchedResultsChangeUpdate: [self configureCell:[self.tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath]; break; case NSFetchedResultsChangeMove: [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; // Reloading the section inserts a new row and ensures that titles are updated appropriately. [tableView reloadSections:[NSIndexSet indexSetWithIndex:newIndexPath.section] withRowAnimation:UITableViewRowAnimationFade]; break; } } - (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type { NSLog(@"controller:didChangeSection:"); switch(type) { case NSFetchedResultsChangeInsert: [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; break; case NSFetchedResultsChangeDelete: [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; break; } } - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller { NSLog(@"controllerDidChangeContent:"); // The fetch controller has sent all current change notifications, so tell the table view to process all updates. [self.tableView endUpdates]; } 

Estoy implementando ambos methods para el número de sección y fila, que devuelve 1 para las secciones y 0 para las filas:

 - (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView { int sections = [[self.fetchedResultsController sections] count]; NSLog(@"sections=%i", sections); return sections; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { id<NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section]; int rows = [sectionInfo numberOfObjects]; NSLog(@"rows=%i", rows); return rows; } 

¿Ha intentado realizar manualmente una consulta con su request de recuperación para asegurarse de que devuelve lo que espera? En su fetchedResultsController personalizado, intente hacer lo siguiente:

 NSArray *entities = [itemController.managedObjectContext executeFetchRequest:fetchRequest error:&error]; NSLog(@"%d",entities.count); 

y mira lo que regresa.

Además, intente configurar su fetchedRequestController sin un caching. Es posible que esté reutilizando el mismo caching por su nombre en otras partes de la aplicación.

La asignación al delegado:

  self.fetchedResultsController.delegate = self; 

Última línea:

 return self.fetchedResultsController; 

Esto dará como resultado una llamada circular a este método. No escriba un código como este.

Los puntos críticos en esta llamada son managedObjectContext, sortDescriptor y la entidad. Por lo tanto, asegúrese de que ninguno de ellos sea nulo y que los valores sean los esperados.

 static NSString *const NSString *kMyFetchedResultsControllerCacheName = @"RootCache"; - (NSFetchedResultsController *)fetchedResultsController { if (_fetchedResultsController == nil) { [NSFetchedResultsController deleteCacheWithName:]; RBGameItemController* itemController = [RBGameItemController shanetworkingInstance]; NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; NSEntityDescription *entity = [NSEntityDescription entityForName:NSStringFromClass([GameItem class]) inManagedObjectContext:itemController.managedObjectContext]; [fetchRequest setEntity:entity]; NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:NO]; [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]]; [fetchRequest setFetchBatchSize:20]; NSFetchedResultsController *fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:itemController.managedObjectContext sectionNameKeyPath:nil cacheName:kMyFetchedResultsControllerCacheName]; self.fetchedResultsController = fetchedResultsController; fetchedResultsController.delegate = self; } return _fetchedResultsController; } 

Finalmente, siempre debe asegurarse de que se llama a performFetch, probablemente en viewDidLoad :

 NSError *error = nil; [self.fetchedResultsController performFetch:&error]; if (error != nil) { NSLog(@"%@", error.localizedDescription); } 

pasando nil para el nombre de caching resolvió el problema para mí también … todavía no estoy seguro de por qué.