CoreData NSTableView et to-many relationship

regattaregatta Membre
12:52 modifié dans API AppKit #1
Bonjour à  tous,

j'essaye de développer une petite base avec coredata et des 'to-many relationship'.
L'interface graphique est faite par un alt-glisser sur IB (tableview avec many objets).

Elle a 3 entités (pour simplifier) : Site, Mineraux et Mineraux_site
Site contient un attribut (nom) et un relationship vers Mineraux_site
Mineraux  contient un attribut (nom) et un relationship vers Mineraux_site
Mineraux_site contient un attribut (frequence) et 1 relationship Mineraux et 1 vers Site

Site <-->> Mineraux_site <-->> Mineraux

Je saisi des sites et des minéraux sans problème ; ils s'ajoutent dans les tableview.

Si je fais un add sur Mineral_site, le popupButton de Minéraux affiche "Relationship objects for <NSCFSet..."  et la liste des minéraux saisis et non pas que la liste des minéraux saisis !

Les minéraux ne peuvent pas être sélectionnés depuis le popupButton !

Une idée pour  résoudre le problème ?
A+

Réponses

  • 12:52 modifié #2
    Salut et bienvenue!

    La solution à  ton problème consiste à  passer par un NSArrayController pour alimenter ton popup. Tu bindes le contentSet à  la relation considérée. Puis pour le PopUp, tu bindes le content à  ton arrayController (avec comme keyPath arrangedObjects) et le contentValues à  ton arrayController (avec comme keypath arrangedObjects.nom).

    ++
  • aranaudaranaud Membre
    12:52 modifié #3
  • regattaregatta Membre
    12:52 modifié #4
    Merci pour les réponses, mais je n'ai pas tout compris à  la réponse de Renaud !

    j'ai déjà  un NSArrayController par entité et j'avais bindé le popupButton (et son équivalent dans le NSTableView) sur le controlleur pour les minéraux.

    Faut-il ajouter un autre NSArrayController et si oui, que veux tu dire par binder le contentSet (ca c'est clair) à  la relation considérée (ca beaucoup moins) !

    Merci pour le tutorial, mais cela ne m'aide pas.
    Mon code fonctionne si je n'ai pas de "to-many relationship"

    A+
  • 12:52 modifié #5
    Oui il faut rajouter un NSArrayController. Si par exemple la relation qui t'intéresse est mineraux, tu ajoutes le keyPath pour le binding est selection.mineraux et l'objet bindé est le arrayController de mineraux_sites
  • regattaregatta Membre
    12:52 modifié #6
    Ok, cette partie semble bonne dans le code que j'avais modifié.

    Ajout d'un NSArrayController et bind du contentSet du nouveau controlleur par selection.nom de la relationShip vers mineraux(Array controleur de mineraux_sites).

    Pour le popuButton, j'ai bindé le content par arangedObjects(nouveau controlleur).
    J'ai bindé le contentValues par arrangedObjects.nom de la relationShip vers mineraux(Array controleur de mineraux_sites).

    Le popupButton m'indique "Aucune valeur" et rien d'autre !

  • regattaregatta Membre
    12:52 modifié #7
    Bonjour,

    malgrès de nombreux tests, ca ne fonctionne pas chez moi !!
    j'ai raté quelquechose

    Voici une version simplifiée du code.
    La gestion de mineral_site est sans la gestion du to-many dans le tableview et devrait être avec sur le popupButton

    A+

    [Fichier joint supprimé par l'administrateur]
  • aranaudaranaud Membre
    12:52 modifié #8
    Dans les bindings : tu n'as pas renseigné tous les contents. Il faut aussi ajouter des information dans les "Model Key Path".
    Sinon, c'est l'objet entier qui est affiché.

    [Fichier joint supprimé par l'administrateur]
  • regattaregatta Membre
    12:52 modifié #9
    dans 1135960831:

    Dans les bindings : tu n'as pas renseigné tous les contents. Il faut aussi ajouter des information dans les "Model Key Path".
    Sinon, c'est l'objet entier qui est affiché.


    Sur le popupButton ou la colonne du tableView site de mineral_site que tu semble indiquer, cela fonctionne parfaitement ?

    Le principe du code est de renseigner des sites et des minéraux en les ajoutant avec les boutons ADD pour définir des sites (où se trouvent des minéraux) et des minéraux.
    La zone mineral_site permet de faire la liste des minéraux se trouvant sur les sites en indiquant leur fréquence (rare, fréquent, etc...).

    Après avoir renseigner des sites et des minéraux, je sélectionne saisi un site des mineraux_site, un minéral qui si trouve et je renseigne sa fréquence.
    La classe MineralSiteArrayController permet de n'afficher que les minéraux pour le site sélectionné dans la partie site, ou tous, si aucun site n'est sélectionné (on peut surement le faire avec les bindings aussi).

    La sélection du site fonctionne depuis le popup et/ou le tableView (to-one relationShip) mais pas le choix du minéral (to-many relationShip).

    De plus, pour la création de l'interface pour les sites, les minéraux et minéraux_site, c'est IB qui a codé directement les bindings (alt + glisser) (pour un to-one relationShip par défaut je suppose).

    Je suis plus à  l'aise dans le codage que dans la compréhension des bindings.

    Merci pour ton aide car je recherche une solution depuis quelques jours déjà 

    A+
  • 12:52 modifié #10
    Quelques remarques:
    Dans MineralSiteArrayController.m

    [tt]([nomSite compare:clef primitiveValueForKey:@&quot;site&quot;] primitiveValueForKey:@&quot;nom&quot; == NSOrderedSame)[/tt]
    Ne pas utiliser primitiveValueForKeyPath sauf dans le sous classage de NSManagedObject. dans ce genre de cas, faire:
    [tt][clef valueForKeyPath:@site.nom][/tt] c'est fait pour ça.

    Toujours dans ce fichier, je ne comprends pas l'intérêt de ton sous classage: tu peux tout faire avec les méthodes existantes de NSArrayController. Regarde la documentation des méthodes setSortDescriptors: et setFilterPredicate:. Mais il y a une incohérence dans ton interface: tu ne peux pas filtrer pour les sites dans cette fenêtre, car c'est la seule façon de rentrer des minéraux (ou alors j'ai rien pigé à  ce que tu veux faire; et le fait d'utiliser les interface par défaut de CoreData n'arrange absolument rien...).

    En tous cas, si tu n'as jamais fais de Cocoa avant, CoreData et les bindings sont à  éviter. Malgré leur "évidence" lorsqu'on se limite à  un tutorial, ce n'est que rarement le cas lorsqu'on veut les appliquer en pratique, spécialement lorsqu'on ne connait pas le framework. Loin de moi l'idée de vouloir te décourager, mais comme pour tout, il vaut mieux commencer par le début.
  • regattaregatta Membre
    12:52 modifié #11
    Merci pour tes remarques sur le code

    Pour ce qui de cocoa, j'ai développé le même type de base avec SMySQL + MySql et je souhaite voir ce que l'on peut faire avec CoreData

    L'interface doit permettre de saisir de données ou de visualiser suivant un mode utilisation ou renseignement de la base.
    Il y a en fait 3 fenêtres principales : minéraux, sites, pièces qui permettent de saisir des renseignements sur les minéraux, sur des sites et ce qu'ils contiennent et sur les échantillons d'une collection.
    Pour les besoins, j'ai ajouté la saisie des minéraux sur la même fenêtre que les sites.

    Le fait de sélectionner un site dans l'entité site ne fera apparaà®tre que les minéraux de ce site avec leur fréquence (en autre) et si on ne sélectionne aucun site, aucun minéral ne devra apparaà®tre.

    Pour ce qui est du to-many relationShip, j'ai essayé de modifier le code comme tu me l'a indiqué, mais j'ai du manquer quelquechose

    A+
  • 12:52 modifié #12
    Bon j'ai un peu tenté de regarder ton truc. Par bindings, je ne trouve pas comment faire, j'ai en effet l'impression qu'il faut passer par du code pour gérer l'ajout d'un mineral dans le mineral_site à  la main.
Connectez-vous ou Inscrivez-vous pour répondre.