2011-12-04 12 views
6

Próbuję uzyskać NSFetchedResultsController pracy z moim tableview, ale pomimo moich najlepszych starań, aby go poprawnie skonfigurować, zawsze zwraca żadnych wierszy. Otworzyłem mój magazyn danych przez Finder i sprawdziłem przez edytor SQLite, że istnieje wiele rekordów, ale zawsze zwraca zero. czego mi brakuje?NSFetchedResultsController zawsze zwraca żadnych wierszy

klienta getter dla kontrolera:

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

jestem pobierania danych w viewDidLoad:

- (void)viewDidLoad { 
    [super viewDidLoad]; 

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

wyniki Pobrane delegat:

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

Ja realizacji obu metod sekcji i numer wiersza, który zwraca 1 dla sekcji i 0 dla wierszy:

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

Odpowiedz

11

Czy próbowałeś ręcznie wykonać zapytanie z prośbą o pobranie, aby upewnić się, że zwraca to, czego oczekujesz? W swoim zwyczajem fetchedResultsController spróbować zrobić:

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

i zobaczyć, co wraca.

Spróbuj również skonfigurować swój fetchedRequestController bez pamięci podręcznej. Możliwe, że ponownie używasz tej samej pamięci podręcznej po nazwie w innych częściach aplikacji?

+1

Więc zrobiłem pobrać i powrócił wierszy spodziewałem. To co zrobiłem, było przejściem 'nil' dla cacheName. To nie powinno być problemem, ponieważ jest to jedyne miejsce, w którym mam 'NSFetchedResultsController', więc jestem zdziwiony, dlaczego wystąpił problem. –

+0

@WayneHartman przekazując zero dla nazwy pamięci podręcznej rozwiązało ten problem również dla mnie. Nie używam cache nigdzie indziej w aplikacji, więc nie jestem pewien, dlaczego określenie tego tutaj dało mi zerowe wyniki. – deepwinter

0

Podanie zero dla cacheName rozwiązało problem dla mnie również ... nie wiem jeszcze dlaczego.

5

Przypisanie do delegata:

self.fetchedResultsController.delegate = self; 

Ostatni wiersz:

return self.fetchedResultsController; 

To spowoduje okrągłym wywołanie tej metody. Nie pisz tego kodu.

Punktami kluczowymi w tym wywołaniu są managedObjectContext, sortDescriptor i encja. Upewnij się więc, że żadna z nich nie jest zerowa i że wartości są takie, jakich oczekujesz.

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

Wreszcie, zawsze trzeba się upewnić performFetch nazywa, prawdopodobnie w viewDidLoad:

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

Z pewnością zdzieliłabym za to samo moje i półtora roku temu. ;) –

Powiązane problemy