2010-12-12 17 views
1

Mon application iPhone (4.1.2) dispose d'un menu dont chacune des entrées mène à une vue de table différente remplie par NSManagedObject sous-classes. J'utilise le même contrôleur de vue pour chacun, mais ce qui est différent est le prédicat de la requête d'extraction, de sorte que des données différentes sont affichées en fonction de l'élément de menu choisi par l'utilisateur. Assez simple. Tout fonctionne correctement avant d'enregistrer réellement le contexte d'objet géré. Cependant, les choses vont bizarre après l'application entre l'arrière-plan et l'avant-plan pénètre à nouveau, parce que je suis en utilisant ceci:Bogue Weird Core Bug

- (void)applicationDidEnterBackground:(UIApplication*)application { 
    NSError *error = nil; 
    if(managedObjectContext != nil) 
     if([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) { 
      NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
      abort(); 
     } 
} 

j'ai pensé que ce serait un bon moment pour enregistrer mes données. Mais après que cela est arrivé, après que j'appelle performFetch: sur mon contrôleur de résultats récupérés, ses fetchedObjects sont les objets récupérés de la demande de récupération PREVIOUS, et non le nouveau. Autrement dit, si je fais:

// Choose menu item 1 

[self.fetchedResultsController performFetch:nil]; // With fetch request 1 
NSLog(@"%i objects were fetched", [[self.fetchedResultsController fetchedObjects] count]); // Items for fetch request 1 

// Go back to menu, choose menu item 2 for new fetch request 

[self.fetchedResultsController performFetch:nil]; // Fetch request 2 
NSLog(@"%i objects were fetched", [[self.fetchedResultsController fetchedObjects] count]); // Items for Fetch request 2 

// Hit home button, applicationDidEnterBackground: is called 
// Relaunch 
// Choose menu item 1 

[self.fetchedResultsController performFetch:nil]; // With fetch request 1 
NSLog(@"%i objects were fetched", [[self.fetchedResultsController fetchedObjects] count]); // Items for fetch request 2 - HUH? 

La question est donc d'appeler save: sur mon contexte d'objet géré. Si je n'enregistre jamais les données, les requêtes d'extraction ne sont jamais mélangées comme ça, mais une fois que je le fais, c'est comme si les anciennes requêtes d'extraction étaient sauvegardées, même si le fetchedResultsController lui-même n'est créé que par la méthode viewDidLoad de mon contrôleur.

Quelqu'un a-t-il une idée de ce qui se passe?

MISE À JOUR: Plus de code.

- (void)viewDidLoad { 
    delegate = (MAAppDelegate *)[[UIApplication sharedApplication] delegate]; 
    managedObjectContext = delegate.managedObjectContext; 

    [self.fetchedResultsController performFetch:nil]; 
    NSUInteger count = [[self.fetchedResultsController fetchedObjects] count]; // Bug is detected here 

    // ... 
} 

- (NSFetchedResultsController *)fetchedResultsController { 
    if(_fetchedResultsController) 
     return _fetchedResultsController; 

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Tweet" inManagedObjectContext:managedObjectContext]; 
    NSPredicate *predicate = nil; 
    if([self.navigationItem.title isEqualToString:@"Personal"]) 
     predicate = [NSPredicate predicateWithFormat:@"account.username = %@ AND user.username = %@", delegate.currentAccount.username, delegate.currentAccount.username]; 
    else if([self.navigationItem.title isEqualToString:@"Favorites"]) 
     predicate = [NSPredicate predicateWithFormat:@"account.username = %@ AND favorited = YES", delegate.currentAccount.username]; 
    else 
     predicate = [NSPredicate predicateWithFormat:@"account.username = %@", delegate.currentAccount.username]; 
    [fetchRequest setEntity:entity]; 
    [fetchRequest setFetchBatchSize:20]; 
    [fetchRequest setPredicate:predicate]; 

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"tweetID" ascending:NO]; 
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil]; 

    [fetchRequest setSortDescriptors:sortDescriptors]; 
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest 
                           managedObjectContext:managedObjectContext 
                            sectionNameKeyPath:@"retrieved" 
                              cacheName:@"Root"]; 
    aFetchedResultsController.delegate = self; 
    self.fetchedResultsController = aFetchedResultsController; 

    [aFetchedResultsController release]; 
    [fetchRequest release]; 
    [sortDescriptor release]; 
    [sortDescriptors release]; 

    return _fetchedResultsController; 
} 
+0

Il est presque certain que le problème ne réside pas dans la sauvegarde du contexte d'objet géré dans la méthode applicationDidEnterBackground:. Veuillez publier le code de vos méthodes viewDidLoad et fetchedResultsController. –

+0

Message original mis à jour. –

Répondre

1

Mettez-vous en cache dans chaque sous-vue et, si oui, utilisez-vous un nom différent pour chaque cache?

+0

Suis-je en train de mettre en cache quoi? –

+0

vos résultats récupérés. dans l'extrait de code affiché, le code correspondant est 'cacheName: @" Root "];' chaque FRC peut avoir un nom de cache ... des choses étranges peuvent se produire si elles partagent un nom – griotspeak

1

Il est difficile de dire sans voir le code supplémentaire, mais le problème que vous rencontrez est probablement dû aux premières lignes dans votre méthode fetchedResultsController:

if(_fetchedResultsController) 
     return _fetchedResultsController; 

Ce qui se passe est que - juste une supposition - vous êtes la réutilisation de la _fetchedResultsController précédente qui a été configuré en utilisant le prédicat pour chercher demande 2. C'est, dans votre méthode viewDidLoad la ligne

[self.fetchedResultsController performFetch:nil]; 

n'est pas instanciation d'une nouvelle NSFetchedResultsController comme y ou pense: le précédent est renvoyé immédiatement lors de l'appel fetchedResultsController, en raison des deux lignes initiales.