[Résolu] Delete rules pour une double relation Core Data

berfisberfis Membre
mai 2014 modifié dans API AppKit #1
Bonsoir,


Je ma bagarre avec les delete rules des relations entre entités Core Data, soit je n'y comprends rien, soit j'ai un retain cycle quelque part...


Eleve <
>> Resultat <<
> Test <<
> Classe


L'affichage me donne ce que je veux, c'est quand je tente de détruire une entité que ça ne marche pas.


Elève --->> Resultat : Cascade

Eleve <--- Resultat : Nullify

Resultat <<--- Test : Cascade

Test <--- Resultat : Nullify


Donc:

Si je retire un élève, ses résultats sont supprimés, mais si je supprime un résultat l'élève reste.

Si je supprime un test, les résultats sont supprimés, mais si je supprime un résultat le test reste.


Si je supprime un élève ou un test, cela fonctionne comme prévu dans l'application Core Data Editor, mais pas dans la mienne: Si un test est supprimé, il reste dans la base, mais sa Classe est à  NIL. Les résultats restent attribués à  l'élève, et au test. En fait on se retrouve avec



Eleve <
>> Resultat <<
> Test Classe


Donc je penche pour un retain cycle, mais comment s'en assurer? Quel devrait être le type des attributs? J'ai dérivé les classes "Eleve", "Test" et "Resultat" mais comment déclarer leurs propriétés?


Un coup de main serait le bienvenu... D'avance merci.

Réponses

  • LarmeLarme Membre
    mai 2014 modifié #2

    T'as fait un clean ?


     


    Cf ceci


  • berfisberfis Membre
    mai 2014 modifié #3

    Je ne les compte plus... et détruire le storedata idem...


     


    Dans mes classes dérivées, je n'ai jamais deux retain qui se croisent pourtant. Par exemple, un test A des résultats (retain) et un résultat APPARTIENT A un test (assign)...


     


    Une propriété assign a une delete rule Nullify, une propriété retain a une delete rule Cascade...


  • colas_colas_ Membre

    À tout hasard, avant de supprimer une entité vérifie si toutes les relations inverses sont bien renseignées (c'est-à -dire que Core Data a bien symétrisé les liens entre tes objets). Si ce n'est pas le cas, ça pourrait expliquer ton cas.


  • berfisberfis Membre

    Salut colas2,


     


    J'ai vérifié dans le Core Data Editor (pratique cette appli) et tout est bien relié. Dans le sens de la création, ça marche très bien, c'est la suppression qui pose problème.


     


    Je regarde du côté de refreshObject:mergeChanges...


  • colas_colas_ Membre
    mai 2014 modifié #6

    Est-ce que tu sauves tes données avant de faire ton delete ça change quelque chose ?


    Cette appli a l'air effectivement super !


  • berfisberfis Membre
    mai 2014 modifié #7

    Je crois que j'ai mis la main dessus. C'est la partie Contrôleur de l'application qui était "fautive" (en fait, elle faisait parfaitement son travail, j'ai juste oublié de réfléchir jusqu'au bout...)


     


    Pour pouvoir détruire un Test appartenant à  une Classe, je suis obligé de les lister dans une NSTableView, avec des boutons + -  pour agir sur la liste.


     


    Comme je suis un aficionado du binding, j'ai donc associé un contrôleur à  cette table et... lié son Content Set au set de la Classe courante (oui oui, les puristes, il existe un binding pour un set, même dans un array controller. Et ça fonctionne.)


     


    Le souci, c'est qu'à  ce moment-là , le contrôleur ne gère plus les Tests eux-mêmes, mais le set de la Classe auquel ils appartiennent. Et donc, en cliquant sur mon bouton -, je ne supprime pas le Test, je le retire du set qui le contient.


     


    Je me retrouve donc avec un Test qui flotte à  la dérive dans le document, qui n'appartiendra plus à  une Classe et donc ne sera plus listé dans la table...


     


    Après cette illumination très matinale " j'avais dû continuer à  y réfléchir en dormant " restait à  trouver une solution (nan, pas de datasource, merci). J'en ai vu deux:


    1) le bouton remove passe par le appDelegate (beurk)


    2) dériver l'arrayController et modifier sa méthode remove.


     


    J'ai fini par créer une classe ContentSetController qui implémente remove ainsi:



    - (IBAction)remove:(id)sender
    {
    NSManagedObject *mo = self.selectedObjects.lastObject;
    NSManagedObjectContext *moc = mo.managedObjectContext;
    [moc deleteObject:mo];
    }

    Et du coup ça marche, bien sûr... Merci Core Data Editor, sans lui je ne me serais aperçu de rien, puisque le graphe restait cohérent.


     


    La solution avait déjà  été donnée par Kubernan dans le lien indiqué par Larme, mais le problème, lui, était différent:



     


    Sauf erreur de ma part, si tu mets à  nil, tu indiques simplement que les objets ne sont plus liés. Ils ne sont pas détruits.


    Il faut faire un deleteObject (sur B pour provoquer ton delete en cascade.



Connectez-vous ou Inscrivez-vous pour répondre.