2010-08-24 6 views
0

J'utilise un NSFetchedResultsController pour remplir le contenu de mon UITableViewController.Actualisation et suppression de contenu dans une erreur de thread d'arrière-plan (NSFetchedResultsController)

J'utilise un NSOperation pour recueillir des données d'un webservice (j'utilise un ManagedObjectContext séparé comme il est un autre thread)
Lorsque les données sont enregistrées mon ViewController (Wich est le NSFetchedResultsControllerDelegate) est appelé et je fusionner mon MOCs utilisant mergeChangesFromContextDidSaveNotification

#pragma mark - 
#pragma mark Parsers delegate 

- (void)parserWillSave:(id)parser{ 
    TopNewsParser *emp = (TopNewsParser *)parser; 
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(parserContextDidSave:) name:NSManagedObjectContextDidSaveNotification object:emp.managedObjectContext]; 
    [NSFetchedResultsController deleteCacheWithName:@"aLaUne"]; 
} 

- (void)parserDidSave:(id)parser{ 
    TopNewsParser *emp = (TopNewsParser *)parser; 
    [[NSNotificationCenter defaultCenter] removeObserver:self name:NSManagedObjectContextDidSaveNotification object:emp.managedObjectContext]; 
} 

/** 
Notification from the add controller's context's save operation. This is used to update the fetched results controller's managed object context with the new book instead of performing a fetch (which would be a much more computationally expensive operation). 
*/ 
- (void)parserContextDidSave:(NSNotification*)saveNotification { 
    DLog(@""); 
    NSManagedObjectContext *fetchContext = [_fetchedResultsController managedObjectContext]; 
    // Merging changes causes the fetched results controller to update its results 
    [fetchContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:) 
            withObject:saveNotification 
           waitUntilDone:YES]; 


} 

Pour le NSFetchedResultsControllerDelegate j'utilise le code de l'échantillon Livres CoreData

#pragma mark - 
#pragma mark NSFetchedResultsControllerDelegate 

- (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 { 
    //ALog(@"indexPath: %@ newIndexPath : %@ | type : %d # %@",indexPath,newIndexPath,type,anObject); 
    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:[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 { 

    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 { 
    UIBarButtonItem *reloadButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh 
                        target:self        
                        action:@selector(refreshTableViewContent)]; 
    reloadButton.accessibilityLabel = @"Reload"; 
    self.navigationItem.leftBarButtonItem = reloadButton; 

    // The fetch controller has sent all current change notifications, so tell the table view to process all updates. 
    [self.tableView endUpdates]; 

} 

Mon problème est quand charger un nouveau contenu où un objet a été supprimé, mon tableView est foiré! La ligne est toujours visible même si mon countOfRow est réduite de 1:

Puis quand je défiler vers le bas de mon tableview est vide (seulement les 4 lignes visibles) sont toujours dans le tableview sinon il est un ScrollView blanc

Dans la console je peux voir le message suivant.

Erreur d'application grave. Une exception a été interceptée par le délégué de NSFetchedResultsController lors d'un appel à -controllerDidChangeContent: *** - [NSMutableArray removeObjectAtIndex:]: index 0 au-delà des limites de tableau vide avec userInfo (null)

Dans beggining J'pensais cela était dû au cache de mon NSFetchedResultsController mais même quand je le désactiver j'ai le même problème.

Est-ce que quelqu'un a une idée sur la façon de résoudre ce problème?

Répondre