11
votes

Débogage NsObjectorCESPESSIBLEException - NsmanagedObject avec ID: 0x123456789 a été invalidé

J'ai un bug que j'ai du mal à suivre. Je crois ce qui se passe est que je supprime un objet de la base de données sous-jacente tandis que un autre contexte d'objet géré (dans un autre fil) a une faute sur elle et obtient la "NsObjectAccessibleXException" lorsqu'elle essaie de remplir le défaut.

Le scénario est que j'ai une vue d'accéder aux données à travers un contexte dans l'arrière-plan, une autre menace porte les enregistrements hors date du magasin. Le thread de fond ne doit être que purger des objets qui ne sont pas requis par la vue - ce n'est évidemment pas le cas, mais j'ai du mal à suivre exactement ce qui se passe. Au moment où je vois le défaut, il est trop tard et c'est un défaut relativement rare qui ne se produit principalement que sur le terrain.

D'où ma question: Y a-t-il des astuces qui me manquent lors du débogage de Coredata - puis-je suivre les viftes des objets d'un contexte dans un autre? C'est à dire. Quand je supprime mon objet est un moyen facile de voir si d'autres contextes ont une référence à ce même objet? En utilisant cela, je pourrais créer un code de test pour vérifier ma logique et trouver l'erreur.


4 commentaires

Jim, pourquoi avez-vous abandonné ma balise iPhone? Je travaille sur iPhone, donc je n'ai pas de liaisons Coredata.


Roger - je mets la balise iPhone. Mais c'est vraiment un problème de données de base générique qui peut se produire sur une plate-forme de bureau ou mobile.


J'ai donc diagnostiqué cela et c'est un problème d'iPhone bien que cela puisse arriver n'importe où.


Ben, pourquoi supprimer la balise spécifique à l'iPhone et ajouter une touche de cacao-touch (étiquette spécifique iPhone)?


4 Réponses :


1
votes

Quel est le deuxième contexte qui fait quand il essaie de défaut dans l'objet qui a été supprimé du magasin persistant?

Cela ressemble à un bogue qui peut avoir 2 parties: vous ne fusionnez pas des modifications du contexte de votre pair et que vous disposez d'un bogue logique qui vous empêche d'utiliser un objet dans le fil B qui a été supprimé dans le fil A.

Généralement, vous voudrez fusionner des modifications à partir d'un contexte de pair à l'aide de - [NSManageDObjectContext MergechangesfromContextDidSacotification:] .


3 commentaires

Je pense qu'il y a deux bugs ici et je suis d'accord avec ce qu'ils sont :-( ce dont j'ai besoin, c'est un moyen de les suivre.


Fusiontez-vous des changements de vos contextes de pair? Pour débogage des buts, vous pouvez enregistrer des objets supprimés chaque fois qu'un contexte est enregistré. Si vous savez quels sont tous les autres contextes existants, vous pouvez également examiner les objets enregistrés auprès de ces contextes, mais vous devrez le faire de manière sûre.


Tu as raison. J'ai décidé que j'ai besoin de réparer la situation entière pour résoudre ce défaut. Ce n'est pas trivial mais probablement bon pour ma santé.



7
votes

J'ai rencontré cette erreur plus tôt et que le coupable était que je nettoyais mon contexte (terminé) mon contexte puis a essayé ensuite d'accéder à un objet (précédemment) géré par ce contexte.

Dans mon cas, le contexte était un contexte "gratter" qui disparaît lorsque la vue a été fermée. Cependant, j'ai eu un travail d'arrière-plan que la vue avait engendré qui voulait mettre à jour l'objet.

J'ai fini par faire un accesseur pour l'objet géré qui renvoyé nul lorsque [GestionedObject Isfault] était vrai. Ensuite, dans mon code, je vérifiais la valeur de ce sélecteur accesseur pour vous assurer que j'avais un objet valide à travailler (par exemple, lorsque mon travail d'arrière-plan a finalement terminé son travail).

Je suis assez nouveau sur les données de base, il y a donc probablement une meilleure façon de le faire, mais je pense que cela a résolu le problème pour moi.


4 commentaires

Jason, merci d'avoir ramené cela à mon attention. J'ai récemment réparé mon erreur, il s'agissait d'une combinaison de nettoyage et de vues de carte de MapKit gardez leur délégué trop longtemps. Dans votre cas, vous ne devriez probablement pas accéder au même contexte NsManageDObject à partir de votre thread de fond - Coredata n'est pas du thread-coffre-fort. Au lieu de cela, vous devriez transmettre une nsmanagedObject à votre tâche de fond.


Oui, tu as vraiment raison. Dans mon cas, je sautais sur le fil principal (où je crée tous les contextes) avant de modifier l'objet, mais ce n'est toujours pas bon lorsque son contexte est passé au revoir.


Quelle est cette "nsmaniedObjectReFérence" que vous parlez? N'existe pas, selon les docs ...


Il signifiait probablement nsmanagedObjecteDed s.



1
votes

La solution était une combinaison de nettoyage et Ce bug de mapkit . Une vue sur la carte tenait son délégué après avoir publié mon NsmanieDObjectContext. Mapkit a demandé au délégué des coordonnées d'une annotation et de mon objet de délégué a essayé d'interroger un objet dans un contexte publié (semblable au problème de Jason).

Le correctif a été tel que décrit dans le blog de Jake - Définissez le délégué à NIL lorsque vous avez terminé la vue Carte.


4 commentaires

Le lien est cassé. En avez-vous le nouveau, ou pouvez-vous expliquer?


Je pensais l'avoir fait. Le problème est que certaines classes détiennent une faible référence à leur délégué et l'envoi de messages après avoir été distribués. Si vous voyez ce problème, assurez-vous de références de délégué (ou de source de données) nulle dans une classe que vous êtes le délégué de.


Merci pour la clarification.


C'était le problème pour moi aussi sur iOS 8.0. Dans le délégué, j'avais accès à un objet géré que j'ai supprimé.



2
votes

Je viens de faire face à ce problème moi aussi. J'ai fait des refactorations pour suivre le modèle "STRAR-CRÉRÉE" d'Apple STRAND> pour une importation groupée de données. J'ai créé un nouveau contexte dédié à l'importation en définissant le sous-agent à Nil comme suggéré. Donc:

NSArray *storedObjects = [defaultContext executeFetchRequest:checkRequest error:&fetchError];


1 commentaires

Juste un peu de note latérale pour les utilisateurs d'iOS. Sur iOS the Undomanager est nil par défaut.