2009-10-05 9 views
4

Pourquoi le [NSFetchedResultsController performFetch:] plante-t-il en recréant un NSFetchedResultsController avec un équivalent NSFetchRequest?Pourquoi NSFetchedResultsController performFetch: plante-t-il en recréant un NSFetchedResultsController avec un NSFetchRequest équivalent?

J'ai une application qui a un contrôleur de table de threads (threads de message). Lorsque vous appuyez sur un thread, il charge un autre contrôleur de vue de table qui utilise un NSFetchedResultsController pour récupérer tous les messages de ce thread et les afficher. J'utilise un NSFetchedResultsController parce que je peux charger les messages en arrière-plan/supprimer/ajouter de nouveaux et ne pas s'inquiéter de les afficher du tout. Le deuxième contrôleur de vue de table est utilisé pour tous les threads, donc quand je tape en arrière puis appuyez sur un autre thread, je supprime juste le NSFetchedResultsController actuel et en configure un nouveau pour le nouveau thread.

Voici les étapes pour reproduire le CRASH:

  1. Tapez sur un fil il me montre les messages.
  2. Rechargez les messages, de sorte que NSFetchedResultsController s'utilise pour afficher les nouveaux messages.
  3. Retournez.
  4. Appuyez sur un autre fil.
  5. Retournez.
  6. Appuyez sur le premier fil.

Lorsque vous appuyez sur le bouton NSFetchedResultsController, le tout est identique au premier. (Même cache et tout). Au lieu de travailler comme il se doit lui donne cette erreur et se bloque:

Program received signal: “EXC_BAD_ACCESS”.

NSFetchedResultsController envoie un message à un objet libéré.

Voici la trace de la pile:

#0 0x95ffd688 in objc_msgSend 
#1 0x0060699b in -[NSFetchedResultsController(PrivateMethods) _computeSectionInfo:error:] 
#2 0x00601bf0 in -[NSFetchedResultsController performFetch:] 
#3 0x0001c170 in -[CMNewMessagesViewController loadMessagesViewControllerForThread:showProfile:] at CMNewMessagesViewController.m:331 

3 est ma méthode

Toutes les idées du tout? Toute aide serait très appréciée.


RÉSOLU!

C'était de ma faute. J'utilisais un sectionNameKeyPath dérivé d'une autre valeur-clé. C'est ok tant que le NSFetchRequest est trié par cette valeur-clé. Le problème était qu'il était généré dynamiquement puisque je ne voulais pas gaspiller de l'espace dans la base de données pour cela. J'ai utilisé une variable d'instance dans la classe NSManagedObject pour cela qui a été nettoyée par didTurnIntoFault.

Maintenant, je pense que la variable d'instance doit avoir été créée puis supprimée puis recréée à un certain point pour amener le tri de NSFetchedResultsController à un arrêt de broyage.

Cela explique pourquoi ne pas avoir un sectionNameKeyPath ou un délégué a résolu le problème.

Maintenant, je suis passé à une valeur-clé enregistrée dans l'objet CoreData et cela semble fonctionner correctement.

Répondre

0

C'était ma faute. J'utilisais un sectionNameKeyPath dérivé d'une autre valeur-clé. C'est ok tant que le NSFetchRequest est trié par cette valeur-clé. Le problème était qu'il était généré dynamiquement puisque je ne voulais pas gaspiller de l'espace dans la base de données pour cela. J'ai utilisé une variable d'instance dans la classe NSManagedObject pour cela qui a été nettoyée par didTurnIntoFault.

Maintenant, je pense que la variable d'instance doit avoir été créée puis supprimée puis recréée à un certain point pour amener le tri de NSFetchedResultsController à un arrêt de broyage.

Cela explique pourquoi ne pas avoir un sectionNameKeyPath ou un délégué a résolu le problème.

Maintenant, je suis passé à une valeur-clé enregistrée dans l'objet CoreData et cela semble fonctionner correctement.

1

Lorsque vous appelez performFetch j'ai eu le même signal EXC_BAD_ACCESS très profond dans la pile du système. Les modifications avec le cache ou quoi que ce soit n'a pas aidé.

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate]; 
    managedContext = [appDelegate managedObjectContext]; 

    NSError *error = nil; 
    NSFetchedResultsController *frC = self.fetchedResultsController; 
    if (![frC performFetch:&error]) { 
     /* */ 
    } 
} 

Dernièrement, j'ai trouvé un petit extrait à ajouter. En fait, le problème était la façon dont j'avais utilisé la gestion de la mémoire iOS (ou n'avait pas utilisé).

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

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Asiakasrekisteri" inManagedObjectContext:managedContext]; [fetchRequest setEntity:entity]; 

    [fetchRequest setFetchBatchSize:200]; 

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

    [fetchRequest setSortDescriptors:sortDescriptors]; 

    NSFetchedResultsController *aFetchedResultsController = 
     [[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedContext sectionNameKeyPath:nil cacheName:nil] retain]; 

    aFetchedResultsController.delegate = self; 
    self.fetchedResultsController = aFetchedResultsController; 

    [aFetchedResultsController release]; 
    [fetchRequest release]; 
    [sortDescriptor release]; 
    [sortDescriptors release]; 
    return fetchedResultsController; 
} 

aFetchedResultsController a eu très courte vie indépendante, mais il a été désallouée avant performFetch. Un conserver a aidé et resultscontroller alloués tenus.

Questions connexes