2010-07-02 4 views
3

J'implémente un UITableViewController en conjonction avec NSFetchedResultsController. Lorsque le UITableViewController est instancié, NSFetchedResultsController est construit (sensiblement de la même manière que l'exemple CoreDataBooks) avec un prédicat différent, basé sur la sélection effectuée par l'utilisateur sur le contrôleur précédent.
Parfois, je mets le prédicat de cette façon:Méthodes NSFetchedResultsControllerDelegate non appelées si son prédicat utilise IN?

predicate = [NSPredicate predicateWithFormat:@"container = %@", aManagedObject]; 

parfois de cette façon:

predicate = [NSPredicate predicateWithFormat:@"container IN (%@)", aNSMutableSetOfObjectsID]; 

Les deux prédicats fonctionne très bien parce qu'ils vont chercher correctement tous mes objets comme prévu. Le problème se produit lorsque j'essaie d'insérer un nouvel objet géré dans la liste lorsque le deuxième prédicat est défini. En fait, dans ce cas, les méthodes déléguées FRC ne sont jamais appelées, donc la tableview n'est pas automatiquement mise à jour.
Je suis sûr que le nouvel objet est correctement ajouté au même contexte utilisé par la FRC, et que sa relation "conteneur" est définie de sorte que le délégué doit être déclenché, mais ce n'est pas le cas!

Ce que j'ai essayé:

Je dis que le second prédicat fonctionne bien parce que si j'ajouter un nouvel objet puis pop le UITableViewController et le pousser à nouveau, ce qui oblige toutes les données à refetched, la nouvelle objet apparaissent dans la liste sans problème.
Un autre test que je fait est de forcer le FRC à recalculé immediatelly après le nouvel objet est ajouté:

NSError *error = nil; 
if (![[self fetchedResultsController] performFetch:&error]) { 
    exit(-1); 
} 
[self.tableView reloadData]; 

le nouvel objet apparaît correctement.

code:

- (NSFetchedResultsController *)fetchedResultsController { 
if (fetchedResultsController == nil) { 
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
    NSManagedObjectContext *managedObjectContext = realEstate.managedObjectContext; 

    [fetchRequest setEntity:[NSEntityDescription entityForName:@"Item" inManagedObjectContext:managedObjectContext]];  
    [fetchRequest setPredicate:[self getBasePredicate]]; 

    NSSortDescriptor *nameDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" 
                    ascending:YES 
                    selector:@selector(localizedCaseInsensitiveCompare:)]; 
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:nameDescriptor, nil]; 
    [fetchRequest setSortDescriptors:sortDescriptors]; 
    [nameDescriptor release]; 
    [sortDescriptors release]; 

    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest 
                           managedObjectContext:managedObjectContext 
                            sectionNameKeyPath:@"sectionIndex" 
                              cacheName:nil]; 
    self.fetchedResultsController = aFetchedResultsController; 
    fetchedResultsController.delegate = self; 
    [aFetchedResultsController release]; 
    [fetchRequest release]; 
} 

return fetchedResultsController; 
} 


// return a predicate for the fetchedResultsController 
- (NSPredicate *)getBasePredicate { 
    NSPredicate *predicate = nil; 

    if ([[managedObject valueForKey:@"subcontainersCount"] intValue] == 0) 
     // container without sons **(FIRST PREDICATE)** 
     predicate = [NSPredicate predicateWithFormat:@"container = %@", managedObject]; 
    else { 
     // container with sons **(SECOND PREDICATE)** 
     predicate = [NSPredicate predicateWithFormat:@"container IN (%@)", [Container allDescendantsObjectID:(Container *)managedObject includeSource:YES]]; 
    } 

    return predicate; 
} 


- (void)addNewItem { 
    Item *newItem = (Item *)[NSEntityDescription insertNewObjectForEntityForName:@"Item" 
                  inManagedObjectContext:realEstate.managedObjectContext]; 
    newItem.name = @"my new item"; 
    newItem.container = aContainerManagedObject; 

    NSError *error = nil; 
    if (![realEstate.managedObjectContext save:&error]) { 
     abort(); 
    } 
} 

Les méthodes NSFetchedResultsControllerDelegate que je utilise sont tirées de la "Plus d'iPhone 3 de développement". Le code complet peut être voir here (pages 30-31, 35).
Je peux poster ici si nécessaire.

Répondre

2

Résolue en remplaçant l'ID d'objet par NSManagedObject dans le prédicat.

Avant: [NSPredicate predicateWithFormat:@"container IN (%@)", aNSMutableSetOfObjectsID];

Après: [NSPredicate predicateWithFormat:@"container IN (%@)", aNSMutableSetOfNSManagedObject];

Pour certaines raisons, le délégué n'est pas appelé FRC si des objets en utilisant prédicat chercher ID au lieu de NSManagedObjects exact.
Je suis en train de tester sur iPhoneOS 3.1.3 et 3.2. Cependant iPhoneOS 4.0 devrait supporter à la fois objectsID et NSManagedObject et appeler correctement les méthodes déléguées FRC, mais je ne peux pas tester sur 4.0 pour l'instant.

+0

Merci! J'avais aussi un problème où le délégué du FRC n'était pas appelé, et bien que ce fût un problème différent, il s'est avéré être un problème avec mon prédicat. –

Questions connexes