Gérer le changement de selection pour une "sous-vue"
Je vais essayer de vous présenter le problème de façon claire.
1) J'ai ma classe Document
Dedans j'ai un NSArrayController : theMainController.
MainController gère des objets.
Je contrôle le array directement dans Document.xib : Previous et Next.
Tout ça marche très bien.
2) J'ai sous-vue gérée par un contrôleur : myHeaderViewController.
Dans cette sous-vue j'affiche des propriétés de l'objet sélectionné.
Dans ma classe Document, j'ai accès à ce myHeaderViewController via une @property.
Comment je m'y suis pris ?
Dans windowControllerDidLoadNib: je fais :
[self setMyHeaderViewController : [[HeaderViewController alloc] init]] ;
Ensuite, je dis à ce controller qui il contrôle (c'est la ligne problématique) :
[self.myHeaderViewController setRepresentedObject:[theMainController selection]] ;
3) Ensuite, dans le xib de HeaderViewController, je fais des bindings sur les propriétés qui m'intéressent via le representedObject
Que se passe-t-il ?
Le premier objet affiché est ok.
Mais, quand je clique sur Next, ça ne marche plus : les champs de HeaderViewController ne sont pas mis à jour.
C'est logique car en cliquant sur Next, le HeaderViewController n'a pas été mis au courant que le representedObject avait changé. Et, dans le binding, il n'a pas moyen de savoir qu'il doit mettre un observateur sur selection.
Comment résoudre ce problème ?
Je voulais savoir si on peut résoudre ce problème en gardant cette façon de faire.
(c'est-à -dire en ne donnant à HeaderViewController que des infos sur l'objet sélectionné)
Une autre façon de faire (je pense) serait de dire à HeaderViewController qui est theMainController.
Merci !
Réponses
Solution : mettre un observateur sur selectedIndex de theMainController et implémenter la mise à jour de la sous-vue dans une méthode appelé lorsque selectedIndex change !
Je ne suis pas très à l'aide avec selectedIndex car il doit changer aussi si le tableau des objets du ArrayController est "réarrangé".
Hello Colas2
Ton appli semble utiliser le pattern Master/Detail.
Dans ce cas, n'utilise qu'un seul contrôleur, le "theMainController". Ta solution des deux NSArrayController t'oblige à lier deux classes via un KVO "à la main" qui recèle toujours des surprises.
Pour la partie Master du contrôleur, ne change rien. Pour la partie Detail, utilise "theMainController.selection" comme début de binding path.
Comme tu utilises "representatedObject", j'en déduis que tu utilises une view-based NSTableView. Vérifie que ce n'est pas un luxe inutile, parce que beaucoup de choses peuvent déjà être accomplies dans une cell-based NSTableView.
Salut je te propose de partir sur une bibliothèque créée par quelqu'un tu peux t'en inspire tu a des images sur la page
Ca rejoint ton idée en gros ca affiche les info sur un aliment ici tu peux changer la classe librement
C'est une sorte de popup avec un fichier .Xib que j'utilise en parallèle avec le storyboard et j'en suis satisfait
J'espere que ça t'aidera : https://github.com/andrewRosenblum/AJRNutritionController
PS : première fois que je répond au problème de quelqu'un mais si tu as des questions n'hésite pas
Am_Me salut!
Ton exemple concerne iOS, je ne crois pas qu'il sera d'une grande utilité pour colas2 (lequel aurait peut-être dû poster sous OSX, d'ailleurs...)
Ah désolé j'ai cru qu'il parlait d'iOS je n'y m'y connait pas trop sur OSX désolé
Ouais, aujourd'hui tout le monde ne parle plus que d'iOS. Il y a bien ces machines un peu lourdes avec un gros écran et un clavier avec des touches dessus, mais ils sont bridés et les programmes sont tous livrés avec... >:(
@Draken: tu vois...
Merci pour vos réponses.
@Berfis :
Non, je n'utilise pas de NSTableView View-based. Ma partie detail ne contient que des champs texte, des cases à cocher, etc.
Mais, je ne peux pas utiliser "theMainController.selection" comme début de binding path. En effet, comme ma partie Detail est dans une autre classe (et donc avec un autre .xib) que la partie Master, je n'ai pas accès à theMainController.
Faut-il que je crée un @property theMainController dans Detail et qu'elle point vers theMainController du Master ?
Je vais essayer !
Je crois que c'est un problème de design, tu es es train d'essayer à nouveau d'établir des liaisons fortes entre deux classes différentes (dans des xib séparés, encore que je me demande ce que des xib viennent faire là -dedans).
L'objet géré par ton contrôleur possède des propriétés. Certaines vont être listée pour retrouver l'objet (par exemple son nom). C'est la partie tableView de ton contrôleur, la partie Master.
A droite de la tableView, tu as les autres propriétés de l'objet sélectionné dans la tableView, genre image, case à cocher, etc.
Tu bindes les colonnes de la tableView sur contrôleur.arrangedObjects.name, par exemple.
Tu bindes les autres contrôles sur contrôleur.selection.option1, par exemple.
... et tu laisses KVO/KVC faire tout le travail, code zéro
Pourquoi pas
Pour toi ça donnerait
Il me semble que la deuxième ligne est plus ce que tu veux faire. Sur le fond, s'ils sont liés, la modification de l'un entraà®ne normalement la modification de l'autre.
@laudema
Merci pour ces idées !
La première ligne ne marche pas : apparemment NSArrayController n'implémente pas bond:toObject:withKeyPath.
J'ai testé la deuxième ligne, qui ne marche pas non plus.
Je t'envoie un toy project qui pourra t'inspirer !
Pour l'instant, la solution vers laquelle je m'oriente est de passer par un delegate qui gère les events "selectionDidChange".
Merci !!!
PS : je continue à réfléchir à ton idée.
Cool !
La deuxième ligne marche !!
Mais il faut plutôt écrire :
Si on peut tirer une leçon de tout ça, c'est ceci : la grande différence entre
Merci !
Hello Colas2,
J'ai jeté un coup d'oeil -- tu as simplement oublié de mentionner que c'est une application Core Data! J'ai juste jeté un coup d'oeil mais...
Tu sous-classes des entités et tes .h et .m ne font strictement rien;
Dans l'init d'une entité, tu crées des entités d'une autre classe;
Tu as défini une relationShip entre tes deux entités qui me paraà®t inutile (à vrai dire, créer deux entités qui font pratiquement la même chose, je ne vois pas l'intérêt);
La fenêtre du document appelle une "custom View" qui n'a rien de custom (un champ de texte).
Le plus surprenant de tout... c'est que l'application ne plante pas -- mais bon, elle ne fait pas grand-chose non plus...
Non seulement je ne vois pas ce que tu cherches à faire, mais il me semble que toi-même tu ne le sais pas. Donc "Back to the Docs!"
https://developer.apple.com/library/mac/#documentation/General/Conceptual/CocoaEncyclopedia/Introduction/Introduction.html
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/Introduction/Introduction.html
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/OOP_ObjC/Introduction/Introduction.html
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/cdProgrammingGuide.html
Je suis passé par là , la plupart des gens de ce forum certainement aussi, tu n'y échapperas pas... Ah, si seulement je pouvais m'asseoir pour la première fois de ma vie à un piano et commencer à jouer du Chopin...
C'est un toy-project !
C'est-à -dire que un petit projet pour vous montrer le cas auquel je suis confronté !
Je voulais pas vous envoyer le gros projet
Je suis d'accord que dans le cas de l'application "iditote" que j'ai créee pour vous montrer, je n'ai pas besoin de passer par une "sous-vue"
PS : Je ne vois pas pourquoi tu dis que c'est étonnant que l'appli ne plante pas. Heureusement qu'un projet si petit ne plante pas :P sinon c'est pas gagné
OK, alors suis l'exemple de Hillegass (d'ailleurs il s'agit aussi de voitures ). J'ai monté mes premières applis Core Data autour de ses exemples -- ils sont sommaires mais posent les bases correctes. Une fois que tu as un noyau solide, tu ajoutes les couches autour. Mais autour du noyau de ton TestCoreData, tu ne vas rien construire de solide...
Core Data est un framework puissant mais à double tranchant. Si tu suis les guidelines, tout se passe comme par magie. Si tu veux sortir des sentiers fléchés, alors là c'est sous-classement pointu, KVO à tes frais et nuits blanches quasi-garanties.
Dans un autre sujet de ce forum, j'ai vu un débutant se lancer dans Core Data direct, avec plusieurs stores qui plus est, et qui s'étonnait (pour ne pas dire se fâchait) qu'on lui conseille de se calmer un peu. Core Data n'est pas un framework d'entrée de gamme! Définitivement pas! C'est la partie modèle de l'application, elle force presque à construire autour d'elle, ce n'est pas un petit "plus" qu'on rajoute au milieu du développement...
Utiliser Core Data sans avoir une idée claire du design de son application, c'est comme dire "Je maà®trise le piano! Mais bon, j'ai jamais utilisé les touches noires, pour jouer du Gershwin je crois qu'on peut s'en passer.." :P
... et sans vouloir te vexer, ton TestCoreData est une application qui joue du piano en étant relié par des ficelles à un saxophone... ::)
Core Data et moi ça n'est pas encore le grand amour et j'ai du mal à obtenir de lui ce que je veux.
Ton "toy-project" ne m'inspirant pas j'en ai refait un sans Core Data
Merci @laudema
Autre solution qui marche, avec cette méthode :
Le point de vue est différent, car le representedObject de brandViewController n'est plus le NSArrayController mais le Car sélectionné (pour que ça marche, il faut donc changer les bindings).
Comment faire pour "un point d'arrêt symbolique sur les Exceptions" ?
Merci
Il suffit d'aller dans le panneau des points d'arrêts (breakpoints navigator commande-6) et dans le bas de cliquer sur le bouton +. Xcode propose alors d'ajouter un point d'arrêt symbolique (une fonction méthode sur laquelle tu veux qu'il s'arrête) ou sur les NSExceptions qui permet de voir la ligne de code ayant provoqué la NSException. Plus rapide que de la rechercher dans la pile via le pop-up où des fois je la rate.
Par contre il peut arriver que la NSException vienne de chez Apple par exemple pour NSOpenPanel + block : je suis obligé de le désactiver sinon Xcode s'arrête 5 ou 6 fois et je peux voir des tas de threads en cours (pour configurer QuickLookPanel par exemple).
C'est peut être dans mon code mais je ne crois pas, ça me le fait dans tous les projets il me semble...
Pour le reste, à part pour le toy-proof-of-concept de TestCoreData je suis d'accord avec berfies, Core Data peut être très déroutant, surtout ajouté aux bindings car Apple utilise plein de méthodes en arrière plan pour retomber sur ses pattes. Entre les bindings spaghettis et les fourneaux Core Data il est parfois difficile de savoir qui a fait tourner la sauce.
Je vois très bien, ayant aperçu des machines comme ça au musée des arts et métiers, pas loin du chariot à vapeur de cugnot, de l'avion de clément ader, de la première machine à coudre et du pendule de Foucault. ça fait peur tous ces engins primitifs, pourtant si innovants à une époque lointaine !
Pour couper court, tu peux télécharger ici une version Core Data basée sur ma compréhension limitée de ton projet.
Temps de réalisation : 15 minutes
Classes dérivées : aucune
Nombre de lignes de code : zéro.
Tu peux t'amuser avec cet exemple, tu verras que les ComboBox complètent la marque et le modèle en fonction de ceux déjà entrés dans ta base de données.
Celle-ci se trouve sous /Users/(ton nom)/Library/Application Support/com.idemsoft.TestCoreDataBis si tu veux la supprimer.
Bonne lecture!
Je comprends... j'ai posté au mauvais endroit tout à l'heure, j'ai fait un tour chez iOS, j'ai été moi-même terrifié par tant de modernité... J'ai failli être englouti par un océan de nibs et de contrôleurs, sans le moindre binding auquel m'accrocher! Heureusement, j'ai retrouvé le chemin de la maison de retraite.
Tu n'y es pour rien, il aurait déjà fallu poster dans la bonne section.
Allez, on déménage.