awakeFromNib exécutée deux fois
Rocou
Membre
Ma méthode awakeFromNib et exécutée deux fois et je ne vois pas comment empêcher cela.
dans la doc il est dit ceci:
It is recommended that you maintain a one-to-one correspondence between your File's Owner objects and their associated nib files. Loading two nib files with the same File's Owner object causes that object's awakeFromNib method being called twice, which could cause some data structures to be reinitialized in undesired ways. It is also recommended that you avoid loading other nib files from your awakeFromNib method implementation.
Mais ce paragraphe est du charabia pour moi.
dans la doc il est dit ceci:
It is recommended that you maintain a one-to-one correspondence between your File's Owner objects and their associated nib files. Loading two nib files with the same File's Owner object causes that object's awakeFromNib method being called twice, which could cause some data structures to be reinitialized in undesired ways. It is also recommended that you avoid loading other nib files from your awakeFromNib method implementation.
Mais ce paragraphe est du charabia pour moi.
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Ils te disent que si tu charges un NIB, par exemple avec un NSWindowController (=File's Owner), et que tu le charges ensuite un autre NIB avec ce même window controller, -awakeFromNib va être appelée deux fois. Comme on se sert de cette méthode pour initialiser les objets connectés, il y a effectivement du grabuge en perspective.
Mais ce n'est pas ton problème. Déjà , c'est quoi ton objet dont la méthode -awakeFromNib est appelé deux fois ? N'as-tu tout simplement pas deux exemplaires de cet objet dans deux NIB différents, ou le même NIB ?
J'avais bien deux NIB (english et french). J'ai supprimé english mais ça ne change rien.
Comment peut-on voir si l'objet est deux fois dans le même NIB?
Il s'agit d'une classe "de type" NSView. J'ai donc un fichier.m et un fichier.h ainsi qu'un petit cube bleu du nom de ma classe dans le MainMenu.xib. Peut-être est-ce ici que ça coince?
PS: mpergand, merci ton code fonctionne parfaitement mais j'aimerais quand même comprendre )
- la première dans la fenêtre
- la seconde, le cube bleu. => À virer.
C'est pour ça que la méthode est appelée deux fois.
Tu peux t'arrêter avec le débogueur dans -awakeFromNib, et tu constateras que self a des valeurs différentes (=> deux instances différentes) lors des deux appels.
Newbie error spotted
grillé par céroce
Merci. Je me doutais bien que le problème venait de là . Mais si je vire le cube bleu, comment réaliser mes liaisons sous IB?
(J'ai notamment une liaison entre un NSScrollView et le cube afin de gérer le scroll de ma vue)
N'est-on pas dans le fil "Grands débutants"?
Le cube bleu est le controller et NSScrollView la vue.
Je n'arrive pas à faire le lien entre mon contrôleur et la vue. Par exemple,
J'ai déclaré un outlet dans mon contrôleur IBOutlet NSView *maVue;
Je réalise la liaison sous IB entre la NSView et mon controleur et à la compilation j'obtiens une erreur: error 'maVue' undeclared (first use in this function)
J'ai dû mal m'exprimer.
Je désire dessiner dans une vue, je dois donc implémenter les méthodes "initWithFrame" et "drawRect".
J'avais donc créé une classe "maVue" de type NSView dans laquelle j'avais implémenté initWithFrame et drawRect. Et à partir de là , je suis perdu.
Les méthodes mouseDown, mouseUp, etc., je dois les mettre où? Dans mon contrôleur ou dans ma classe "maVue"? Comment partager toutes les variables dont j'ai besoin dans mon contrôleur ET dans "maVue"?
C'est pour cela que j'avais tendance à mettre tout mon code dans la classe "maVue" et ne presque pas utiliser mon contrôleur.
Pour reformuler ta question: "Comment échanger les données entre la vue et le modèle", il y a plusieurs réponses possibles; savoir quelle solution adopter fait partie du talent du développeur.
Comme je pense que tu es toujours sur ta vue qui affiche le planning, tu pourrais t'inspirer du modèle de la Data Source utilisé un peu partout dans Cocoa (notamment les table views, p. 102 du livre d'Hillegass).
En effet il faut créer une classe MaVue (note je met une majuscule au nom de la classe "MaVue", c'est une conventionne de nomage que tout le monde utilise, pour les différencier des instances que l'on nomme en général avec la première lettre en munuscule), classe qui sera une sous-classe de (qui dérivera de la classe) NSView, et dans laquelle tu vas réimplémenter drawRect et initWithFrame. C'est donc un nouveau type d'objet, certes une NSView, mais qui sera spécialisée à ton besoin.
Et ensuite dans ton NIB, au lieu de mettre une NSView dans ton interface, tu vas alors placer un objet MaVue (bon dans les faits tu vas placer une NSView parce que tu n'as que ça dans ta bibliothèque dans IB, et tu vas ensuite changer sa classe dans l'inspecteur pour dire qu'en fait c'est pas une NSView générique mais plus particulièrement une MaVue). Tu vas ainsi créer une instance de la classe MaVue dans ton interface graphique.
Ensuite dans ton contrôlleur, si tu as besoin d'accéder à ta vue, tu vas créer un IBOutlet, dont le type est le type de ton objet, et le nom est un nom de variable arbitaire... comme tout IBOutlet. Donc tu vas écrire par exemple [tt]IBOutlet MaVue* maVuePrincipale;[/tt] ce qui va te permettre de relier ton objet de type MaVue que tu as placé dans ton interface à cet IBOulet.
Pour bien te faire comprendre, si tu veux créer une 2e vue qui se comporte pareil que ta première, tu peux placer un autre objet MaVue dans ton interface, et avoir dans ton contrôleur pour y accéder un autre "IBOutlet MaVue* maVueSecondaire" (tout comme tu peux placer plusieurs NSButtons ou NSTextFields dans une fenêtre et avoir des IBOutlets vers ces boutons ou textFields). Ce sera alors une autre instance de la même classe MaVue. Qui appellera comme toutes les instances de la classe NSView (et de la classe MaVue qui en dérive) la méthode "drawRect" de sa classe au moment où elle a besoin d'être dessinée. Et comme il se trouve que c'est un objet de type MaVue, c'est le code implémenté dans MaVue qui sera exécuté, puisqu'il va "remplacer" celui plus générique de NSView pour les instances de classe MaVue.
Tout ceci, j'avais bien compris et ça fonctionne très bien. Ton intervention à le grand mérite de confirmer cela et surtout c'est formulé de façon très claire. Je t'en remercie.
Mais en tant que débutant j'ai du mal à m'exprimer de façon correcte.
Si je veux récupérer les données d'une NSScrollView dans le code de MaVue, comment faire?
J'ai créé un outlet de type NSScrollView dans MaVue mais comment réaliser le lien avec mon NSScrollView?
Avec un cube bleu, c'était facile mais sans ce cube, je ne sais pas comment faire.
Cette question est étrange, une NSScrollView ne contient pas vraiment de données, elle contient d'autres vues ???
On ajoutant une outlet à ta vue et en la reliant à la NSScrollView.
Si la scrollview contient ta vue, tu peux aussi appeler [superview] qui va te renvoyer la NSClipView qui contient ta vue, puis encore [superview] pour obtenir la scrollview.
J'ai l'impression que tu fais quelque chose d'étrange, dis-nous plutôt quel est le résultat recherché.
Oui mais comment physiquement réaliser ce lien?
Sous IB les instances MaVue et NSScrollView sont "confondues", comment tirer un lien de l'une à l'autre?
Et bien dans MaVue, j'ai le code suivant:
Le machin qui s'appelle 'leScroll' (vers le milieu de ce bout de code) doit être de type NSScrollView.
Le but est de faire en sorte que ma ligne et ma colonne d'entêtes restent au même endroit quand l'utilisateur se sert des ascenseurs. La notification sert donc à récupérer les coordonnées du NSClipView au sein de la NSScrollerView (si j'ai bien compris )
A l'origine j'avais déclaré un IBOutlet NSScrollView *leScroll; dans MaVue. Puis j'avais relié mon cube bleu (la seconde instance de MaVue) au NSScrollView. ça fonctionnait très bien.
Mais c'est un peu crade, parce que ça implique que ta vue est dans une scrollview (elle n'est donc plus réutilisable dans une autre situation).
Si ça marchait avec le cube bleu, c'est parce que toutes les instances de MaVue reçoivent la notification. L'instance du cube bleu n'était pas affichée, mais elle réagissait quand même à la notification et la communiquait à la scrollview.
Voici une autre méthode, plus propre: créer un objet intermédiaire (héritier de NSObject) qui reçoit la notification et possède deux outlets: une vers la scrollview et une vers la MaVue.
En changeant le mode d'affichage de la fenêtre principale d'IB afin qu'elle affiche la hiérarchie des instances crées au lieu d'afficher uniquement les objets racine.
Oui, c'est ce que j'ai fait; un objet intermédiaire mais de type NSScrollView, comme ça je récupère directement mes données. Hop!
Merci à tous.
Ha oui, ça serait génial si je savais faire cela
Merci pour les copies d'écran :P
(Ca me paraissait tellement évident que j'ai eu la flemme de les faire moi même )
Ha bon? Chez moi ça ne fonctionne pas comme ça. Je glisse mon lien mais c'est toujours la même chose qui est sélectionné (en l'occurrence la NSView 'MaVue')
Ha super! Je n'avais jamais testé le glissé de lien entre les différents éléments de cette fenêtre
Merci à tous.