tutorial - ios cncontact



NSPredicate non exécuté (1)

J'ai eu le même problème, c'est ce que j'ai compris, et comment je l'ai résolu.

Magical Record a une racine NSManagedObjectContext tant que parent du NSManagedObjectContext par défaut. Lorsque je crée un NSFetchedResultsController dans le contexte par défaut, tout semble fonctionner NSFetchedResultsController , tout comme vous.

Le problème est que tous les nouveaux NSManagedObject reviennent avec leurs ObjectID encore temporaires. Donc, dans mon cas, j'utilisais un NSPredicate pour NSPredicate une requête sur une table associée. Je n'ai pas simplement appelé la méthode d'association car je ne voulais pas tout charger en mémoire et NSFetchedResultsController voulais que NSFetchedResultsController gère les changements, pour moi.

Avec l' ObjectID temporaire, la requête ne trouve aucun résultat et c'est exactement ce qu'elle affiche.

Apparemment, le contexte enfant (par défaut) ne bénéficie pas de la transformation en ID non temporaire, même s'il a été conservé dans le magasin de sauvegarde.

La pire des choses s'est produite quand j'ai essayé de forcer le problème avec obtainPermanentIDsForObjects:error: Core Data s'est plaint qu'il ne pouvait pas satisfaire une faute pour mon instance. Peu importe, il n'y a aucun moyen que ce soit en fait une faute. Le simple rafraîchissement de l'objet n'a pas non plus d'effet. Je soupçonne que c'est un bogue de base de données que presque personne ne chatouille parce qu'ils utilisent simplement les méthodes d'association pour obtenir un NSSet.

Ma solution était d'utiliser le contexte parent pour le NSFetchedResultsController , tout comme dans cette question, Magical Record, save, et NSFetchedResultsController .

J'enveloppais déjà la valeur par défaut dans un nouveau contexte enfant lors de l'édition et, par conséquent, en copiant les instances dans ce contexte d'édition avec createInContext , je n'ai donc pas eu à faire d'autre travail que d'ajouter .parentContext à l'argument.

Incidemment, cela n'est arrivé que sur de nouvelles instances de la source de l'association. Une fois qu'une instance existait à partir du démarrage, elle avait un ObjectID non temporaire et n'a jamais rencontré le problème.

C'est assez marrant. Dans mon application, je crée des milliers d'entrées dans la base de données (dans un autre thread, j'utilise MagicalRecord). Tout semble bien fonctionner (du point de vue arrière-plan / premier plan / contexte).

Lorsque, dans le thread principal, j'essaie de récupérer les données "juste insérées", j'ai découvert le comportement suivant:

- (NSArray *) familiesInCompany:(Company *) company {
  NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"company == %@", company];
  NSPredicate *predicate2 = [NSPredicate predicateWithFormat:@"company.name == %@", company.name];

  NSArray *first = [Family MR_findAllSortedBy:@"name" ascending:YES withPredicate:predicate1];
  NSArray *second = [Family MR_findAllSortedBy:@"name" ascending:YES withPredicate:predicate2];
  NSArray *third = [Family MR_findByAttribute:@"company" withValue:company andOrderBy:@"name" ascending:YES];

  return second;
}

Maintenant, ce que je reçois est:

  • first: est un tableau vide
  • second: contient tous les objets Family , comme prévu
  • troisième: est un tableau vide.

En déboguant l'instruction SQL, j'obtiens ce qui suit:

La "première" déclaration:

CoreData: annotation: temps total d'exécution de récupération: 0,0000s pour 0 ligne.

La "deuxième" déclaration ":

CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZNAME, t0.ZCOMPANY FROM ZFAMILY t0 REJOIGNEZ ZCOMPANY t1 ON t0.ZCOMPANY = t1.Z_PK O t t1.ZNAME =? COMMANDE PAR t0.ZNAME

CoreData: annotation: connexion sql fetch time: 0.0005s

CoreData: annotation: temps total d'exécution de récupération: 0,0007s pour 2 lignes.

La "troisième" déclaration:

CoreData: annotation: temps total d'exécution de récupération: 0,0000s pour 0 ligne.

Ce qui est hilarant, c'est que je ferme l'application (je veux dire vraiment la terminer manuellement) et que je l'ouvre, les trois instructions de «récupération» fonctionnent.

Pourquoi les première et troisième instructions fetch semblent ne jamais être exécutées? Comment creuser dans le problème?