Classes et pointeurs ?!

nicotinenicotine Membre
juin 2010 modifié dans API AppKit #1
Oulala l'objective-c / Cocoa c'est bien mais ca change du C++...

Et la, vindioudevindiou je suis bloqué sur un problème de design patterns !!!! (et de code aussi)

Contexte :
- Une classe Model, possédant une MutableArray d'objets.
- Une classe MainView, qui fait la vue et le controleur, qui instancie Model et en profite pour utiliser gentimment l'array d'objets.
(jusque la tout marche bien !)
- Une troisième classe, qui est une sous-vue, qui est instanciée aussi par MainView et qui doit aller ajouter/retirer, des objets dans l'array.

Pas très compliqué donc mais ..... Comment je fais pour que l'array d'objet puisse être unique et en même temps utilisé par les 2 classes ?! Genre "tient, quand je clique dans ma sousView, ca créer un objet dans mon array sans etre obligé de passer par un message au controleur qui va créer lui même l'objet"

Je voulais passer un pointeur sur l'instance du Model au moment de créer l'instance de ma sousView (comme en C++ quoi) mais je ne trouve pas le moyen de passer quoi que soit dans un constructeur (est ce possible ?!)

Bref c'est bete, mais ca bloque !!! Quelqu'un aurait-il une idée sur une solution ?!

Merci à  tous !

N. qui se dit que C++ c'est pas mal finalement ^^

Réponses

  • CéroceCéroce Membre, Modérateur
    14:58 modifié #2
    dans 1275468248:

    - Une classe MainView, qui fait la vue et le controleur, qui instancie Model et en profite pour utiliser gentimment l'array d'objets.
    (jusque la tout marche bien !)


    Non, dans ce que tu décris, ton objet est un contrôleur (->MainViewController).
    Un objet de la couche Vue s'affiche à  l'écran (et hérite donc en général de NSView, ou de NSWindow, NSMenuBar, etc).

    dans 1275468248:

    - Une troisième classe, qui est une sous-vue, qui est instanciée aussi par MainView et qui doit aller ajouter/retirer, des objets dans l'array.

    Tu veux dire une vue ? Un objet qui hérite de NSView ?

    dans 1275468248:

    Comment je fais pour que l'array d'objet puisse être unique et en même temps utilisé par les 2 classes ?! Genre "tient, quand je clique dans ma sousView, ca créer un objet dans mon array sans etre obligé de passer par un message au controleur qui va créer lui même l'objet"

    La méthode habituellement utilisée sous Cocoa est celle des Data Sources: la vue demande à  un objet, sa data source, de lui donner la valeur à  afficher. La data source est souvent le contrôleur, mais il n'y a pas d'obligation. Essaie d'utiliser une NSTableView pour bien comprendre le principe.

    dans 1275468248:

    Je voulais passer un pointeur sur l'instance du Model au moment de créer l'instance de ma sousView (comme en C++ quoi) mais je ne trouve pas le moyen de passer quoi que soit dans un constructeur (est ce possible ?!)


    Bien sûr, on peut ajouter des arguments aux méthodes d'init:
    - (id) initWithString:(NSString *)theString<br />{<br />	if(self = [super init])<br />	{<br />		// string est une variable d&#39;instance<br />		string = [theString retain];<br />	}<br />	<br />	return self;	<br />}
    


    Mais l'initialisateur désigné de NSView est initWithFrame:.
    De toute façon, passer l'objet à  l'init n'est pas ce qu'il faut faire. Il vaut mieux fixer cet objet avec un setter: ça permet de changer d'objet en cours d'exécution.


    dans 1275468248:

    N. qui se dit que C++ c'est pas mal finalement ^^

    Nous en reparlerons dans six mois...
  • AliGatorAliGator Membre, Modérateur
    14:58 modifié #3
    Hello,

    En complément des explications de Céroce, tu peux peut-être lire ce sujet où un membre avait un peu la même question (pas tout à  fait mais tu vas t'y retrouver, il s'agit de passer un pointeur entre différents ViewControllers), et où j'y explique le principe de delegate (le principe de dataSource est strictement identique, un dataSource n'étant rien d'autre qu'un delegate dédié à  fournir des data).
    Le sujet est pour iPhone, mais le principe général est le même pour Mac (il suffit de remplacer UIView par NSView dans le texte :P)

    Et sinon la suggestion de Céroce est une bonne idée, essaye d'implémenter une NSTableView (il y a des tutos sur le net ou dans la doc Apple -- tout comme d'ailleurs pour les principes de delegate et dataSource), ce petit exercice te permettra de mieux comprendre ce concept / ce DP et d'y voir plus clair sur le moyen le plus propre de communiquer entre les objets.

    Après le principe n'est pas compliqué, un setter qui te permet de passer ton objet Model à  ton Contrôlleur devrait amplement répondre à  ta question finalement, donc bon.
  • nicotinenicotine Membre
    14:58 modifié #4
    Whouaou merci pour cette réponse rapide et complète!

    Alors deux ou trois précisions: MainView n'est qu'un nom (mal choisi certe ^^) pour ma classe héritant de NSView et affiche toute mon interface graphique, à  l'exception d'une fenêtre présentant une bibliothèque d'image et permettant de créer des objets correspondant aux images. Cette fenetre est gérer par ma troisieme classe qui doit donc pouvoir ajouter ces objets dans le Model. d'ou ma question.

    Je ne connaissais pas la méthode des Data sources, je vais donc me renseigner sur tout ça ! Merci encore Céroce, toujours la quand j'ai des soucis ^^

    N.
  • nicotinenicotine Membre
    14:58 modifié #5
    @Aligator et tous ceux qui auraient le même problème :

    Filez sur le liens de Aligator, son résumé en bas de page 1 est fabuleusement clair et compréhensible.

    Merci pour tout, les nuages s'écartent, la lumière descend, les harpes jouent et le code compile ! Youpi ^^

    N.
  • AliGatorAliGator Membre, Modérateur
    juin 2010 modifié #6
    Bonjour,

    Je donnerais juste une précision historique mais qui a son importance :
    • Sous iPhone, quasiment toutes les classes qui utilisent le design pattern "delegate" (ou "dataSource" finalement c'est pareil) utilsent en effet la solution du "@protocol";, c'est ce que l'on appelle un "protocole formel"
    • Mais sous MacOSX, quand les premières versions du SDK OSX est sorti, et qu'à  l'époque c'était encore la version 1.0 d'Objective-C, la directive "@protocol"; et ces concepts de "protocole formel" n'existaient pas (ou je sais plus, peut-être qu'ils existaient, mais ne permettaient pas de rendre certaines méthodes du protocoles optionnelles, j'ai un trou).
    • Toujours est-il que du coup à  l'époque cela était réalisé à  la place par ce que l'on appelle des "protocoles informels" : le principe est quasiment le même, sauf que comme les @protocol n'existaient pas, c'était juste un contrat tacite (en utilisant des catégories sur la classe NSObject : [tt]@interface NSObject(NSURLConnectionDelegate)[/tt] par exemple), qui s'il n'était pas respecté, genre si ton delegate n'implémentait pas la delegate method attendue, ne provoquait pas d'erreur de compilation... alors qu'à  l'exécution quand il va essayer d'appeler la méthode sur le delegate du coup ça va planter. (Voir la doc pour plus de détails sur les protocoles informels)
    • Aujourd'hui, bien sûr, depuis qu'Objective-C 2.0 est sorti et que les @protocol existent et permettent de déclarer des méthodes @required ou @optional à  implémenter pour se confomer au protocole, il est beaucoup plus propre d'utiliser donc un protocole formel @protocol que l'ancienne façon de faire avec les protocoles informels, d'autant que contrairement à  ces derniers, les @protocols formels génèrent un warning si tu as oublié d'implémenter une méthode pour te conformer au protocole, etc.


    Mais bon tout ça pour dire que ne soyez pas surpris dans le SDK de OSX de trouver du coup certains delegates qui utilisent encore ce principe de protocoles informels, c'est purement historique. C'est le cas par exemple de NSURLConnection.

    A terme au fur et à  mesure des mises à  jour des SDK OSX, Apple tend à  remplacer l'usage des protocoles informels qui trainent dans leur API par des protocoles formels, pour faire plus propre. Ca a été le cas pour NSTableView par exemple pour qui le dataSource utilisait précédemment les protocoles informels alors que maintenant il y a un @protocol NSTableViewDataSource
  • zoczoc Membre
    14:58 modifié #7
    dans 1275475780:
    la directive "@protocol"; et ces concepts de "protocole formel" n'existaient pas (ou je sais plus, peut-être qu'ils existaient, mais ne permettaient pas de rendre certaines méthodes du protocoles optionnelles

    C'est exactement ça


    Il manquait le "@optional"; dans Objective-C "1.0".
Connectez-vous ou Inscrivez-vous pour répondre.