2

J'ai un objet d'opération qui crée son propre contexte d'objet géré. L'objet d'opération effectue le calcul essentiellement pour enlever la charge du fil principal tandis que le fil principal se concentre sur l'aspect de l'interface utilisateur. Le MOC de cet objet d'opération partage un magasin persistant commun à travers l'application.Erreur d'objet Coredata dans ManagedObjectContext indépendant vs changements dans le stockage persistant

Il arrive parfois que, pendant l'exécution de l'opération, le MOC du thread principal soit averti des modifications du backend. Ainsi, j'essaye de fusionner les changements de MOC, où certaines des suppressions dans les objets de modèle pourraient se produire. Dans certains cas rares, comme je le constate, l'objet d'opération n'a peut-être pas encore été réalisé et ils sont en état de panne et en même temps le thread principal stocke les changements dans MOC (et dans le stockage persistant). Mon application plante dans un tel scénario.

Comme pour les textes standards, j'ai un MOC dédié pour mes threads et si j'ai bien compris, les données pour les défauts doivent être accessibles à partir du MOC du thread. Est-ce que cela fait une différence dans l'accès aux demandes d'erreurs du MOC du thread, par exemple, le même objet a peut-être été supprimé du magasin?

S'il vous plaît voir cette trace de la pile: enter image description here

Quelle serait une meilleure façon de gérer cela?

Je comprends de ce post: https://stackoverflow.com/a/5722914/260665 que le contexte d'objet géré du thread ne connaît pas les changements sous-jacents au magasin et que les objets en défaut doivent exister dans le magasin. Donc, mieux ce serait soit:

  1. Mise à jour de la collection d'objets dans le fil quand il y a des changements sous-jacents (suppression) dans le magasin en utilisant la notification NSManagedObjectContextDidSaveNotification (A partir de: https://stackoverflow.com/a/5722914/260665)

  2. Vérifiez si le dossier de l » NSManagedObject existe dans le magasin avant d'essayer d'accéder à ses propriétés en utilisant -existingObjectWithID sur le MOC (de: https://stackoverflow.com/a/14297708/260665)

  3. Gérer les exceptions dans le code? (Dernier recours, de: https://stackoverflow.com/a/15361906/260665)

Je ne peux pas aller de l'avant avec des solutions 1 & 2 pour ce n'est pas directement les propriétés du NSManagedObject suis accédaient, j'ai NSFetchedResultController qui ont des descripteurs sorte à l'intérieur duquel l'application se bloque:

-(NSMutableArray*)fetchedTaskObjects 
{ 
    if (nil==fetchedTaskObjects_ && self.taskLocalFetchedResultsController && self.persistantTaskFetchedResultsController) 
    { 
     NSArray *allNonPersistantTasks = [self.taskLocalFetchedResultsController fetchedObjects]; 
     NSArray *allPersistantTasks = [self.persistantTaskFetchedResultsController fetchedObjects]; 

     fetchedTaskObjects_ = [[NSMutableArray alloc] init]; 
     [fetchedTaskObjects_ addObjectsFromArray:allNonPersistantTasks]; 
     [fetchedTaskObjects_ addObjectsFromArray:allPersistantTasks]; 
     NSSortDescriptor *tasksSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"self.mockTaskCounter" 
                       ascending:YES]; 
     NSSortDescriptor *shortTextSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"self.shortText" 
                        ascending:YES]; 
     NSSortDescriptor *headerTextSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"self.accountAssignmentText" 
                        ascending:YES]; 
     [fetchedTaskObjects_ sortUsingDescriptors:[NSArray arrayWithObjects:tasksSortDescriptor, shortTextSortDescriptor, headerTextSortDescriptor, nil]]; 
    } 
    return fetchedTaskObjects_; 
} 

Donc, des suggestions de trouver la bonne solution?

Edit: L'erreur (exception) que je reçois:

CoreData could not fulfill a fault for '0x2b0298a0 <x-coredata://E7E91AFC-5BE6-4996-B28F-92CD115A5D0A/CSTaskRegister/p14746>' 

Quelle ligne il se bloque?

Il se bloque dans l'un des descripteurs de tri où la propriété interne de l'objet géré Faluted est tenté d'accéder par les descripteurs de tri à des fins de tri. Comme c'est un thread, nous ne savons pas exactement quand l'objet sous-jacent est supprimé dans le magasin. Ainsi, le crash de thread se produit parfois aussi dans mon code de calcul de statistiques.Pourquoi combiner le résultat de deux FRC? Parce que, le projet a initialement commencé avec différents MOC pour ces 2 cas, maintenant que le MOC est unique, la différenciation reste encore. Mais je ne pense pas que ce soit un problème d'avoir des CRF discrètes avec son propre but.

+0

Sur quelle ligne de 'fetchedTaskObjects' votre application plante-t-elle? Quelle est l'erreur? Pourquoi combinez-vous 'fetchedObjects' de deux' NSFetchedResultsController'? –

+0

Mise à jour de la question avec les réponses à vos questions. Cependant, j'ai fini par opter pour la 3ème solution d'utilisation de la gestion des exceptions et de négliger les résultats de telles opérations. –

Répondre

1

Assez de recherches, la seule façon d'éviter cela est de mettre à jour la collection en écoutant les notifications (1ère solution mentionnée dans la question) et une autre approche est de vérifier avec -existingObjectWithID (2ème solution en question) avant d'accéder les propriétés. Mais dans mon cas, les descripteurs de tri accèdent en interne aux propriétés des objets gérés supprimés (du stockage persistant). Ne me laisse pas d'autre choix que de gérer l'exception (3ème solution en question) dans le thread et de négliger les résultats (erronés) de ce thread.

1

Si vous ne pouvez pas fusionner ou ne veulent pas toucher le MOC de fonctionnement - par exemple parce qu'il est actuellement utilisé, vous devez garantir que la opération et la mise à jour des données deviennent sérialisé.

L'idée est, lorsque l'opération est en cours d'exécution, il suppose que son point de vue actuel de l'état des données est constante, et donc doit pas être modifié.

Vous avez quelques choix pour garantir ceci:

Si une opération est en cours d'exécution, et vous avez une mise à jour de demande et que vous voulez immédiatement mise à jour des données, y compris le stockage persistant partagé, vous devez d'abord annuler l'opération et attendez que l'opération soit terminée (aucun accès ne se produit par la suite sur le MOC de l'op). Ensuite, commencez à mettre à jour les données dans le MOC principal. Lorsque la mise à jour a été terminée, y compris le stockage persistant, vous pouvez redémarrer l'opération par la suite avec nouvellement initialisé ou correctement fusionné MOC - reflétant l'état actuel des données.

De même, vous pouvez différer la demande de mise à jour jusqu'à la fin d'une opération en cours.

+0

Point prise, bonne suggestion. Je peux reporter la demande de mise à jour dans le MOC principal ou annuler les opérations et attendre qu'elles soient terminées. Pourriez-vous s'il vous plaît ajouter la référence sur Pourquoi la gestion des exceptions n'est pas préférée dans le cacao et l'application devrait cesser de l'exception dans cette réponse, de sorte qu'il servirait de référence pour d'autres à l'avenir? –

Questions connexes