2011-12-04 49 views
6

Estoy tratando de obtener un NSFetchedResultsController trabajando con mi tabla vista, pero a pesar de mis mejores esfuerzos para configurarlo correctamente, siempre no devuelve filas. He abierto mi almacén de datos a través de Finder y validado a través de un editor de SQLite que de hecho hay muchos registros, pero siempre devuelve cero. ¿Qué me estoy perdiendo?NSFetchedResultsController siempre devuelve ninguna fila

captador personalizado para el controlador:

- (NSFetchedResultsController *)fetchedResultsController { 
    if (fetchedResultsController_ != nil) { 
     return fetchedResultsController_; 
    } 

    RBGameItemController* itemController = [RBGameItemController sharedInstance]; 

    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 al obtener los datos de viewDidLoad:

- (void)viewDidLoad { 
    [super viewDidLoad]; 

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

resultados recuperados de delegado:

- (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]; 
} 

Me estoy poniendo en práctica los dos métodos para la sección y número de 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; 
} 

Respuesta

11

¿Ha intentado realizar manualmente una consulta con su solicitud de recuperación para asegurarse de que devuelve lo que esperaba? En su aduana fetchedResultsController intentar hacer:

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

y ver lo que viene de atrás.

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

+1

por lo que hice una zona de alcance y se devuelven las filas que estaba esperando. Lo que terminé haciendo fue pasar 'nil' para el cacheName. Esto no debería haber sido un problema, ya que este es el único lugar en el que actualmente tengo un 'NSFetchedResultsController', así que estoy desconcertado sobre por qué hubo un problema. –

+0

@WayneHartman pasando nil por el nombre de la caché resolvió este problema también. No uso un caché en ningún otro lado de la aplicación, por lo que estoy confundido sobre por qué especificarlo aquí me dio cero resultados. – deepwinter

0

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

5

La asignación al delegado:

self.fetchedResultsController.delegate = self; 

última línea:

return self.fetchedResultsController; 

Estos se traducirá en una llamada circular para este método. No escriba 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 estos sea nulo y de que los valores sean los esperados.

static NSString *const NSString *kMyFetchedResultsControllerCacheName = @"RootCache"; 



- (NSFetchedResultsController *)fetchedResultsController { 
    if (_fetchedResultsController == nil) { 
     [NSFetchedResultsController deleteCacheWithName:]; 
     RBGameItemController* itemController = [RBGameItemController sharedInstance]; 

     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; 
} 

Por último, siempre hay que asegurarse de performFetch se llama, probablemente en viewDidLoad:

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

Ciertamente abofetearé a mi yo de año y medio por hacer lo mismo. ;) –

Cuestiones relacionadas