En même temps, avec ta technique bizarre, pas étonnant qu'il en dessine 2 superposés... à‰trange cette idée de tableau de tableaux ; moi j'aurais fait un tableau unique qui contient pour chaque arc la référence des 2 sommets.
Bah j'essaie de les gérer séparément justement non? Et il faut bien que je les lie aux différents sommets. Il y a un truc que je dois pas saisir dans ce que tu me dis ^^
Et du coup tu peux avoir un NS(Mutable)Array d'objets Sommets, et un NS(Mutable)Array d'arcs, un bout de code vitre fait vaut mieux qu'un long discours :
// on crée 3 sommets par exemple<br />Sommet* s1 = [[Sommet alloc] initWithName:@"A"];<br />Sommet* s2 = [[Sommet alloc] initWithName:@"B"];<br />Sommet* s3 = [[Sommet alloc] initWithName:@"C"];<br />// on initialise notre tableau (variable d'instance) de sommets<br />tableauSommets = [[NSMutableArray alloc] initWithObjects:s1,s2,s3,nil];<br /><br />// Ajout de deux arcs, l'un entre les sommets A et B l'autre entre A et C.<br />Arc* s1s2 = [[Arc alloc] initWithDistance:3 fromSommet:s1 toSommet:s2];<br />Arc* s1s3 = [[Arc alloc] initWithDistance:5 fromSommet:s1 toSommet:s3];<br />// on initialise notre tableau (variable d'instance) d'arcs<br />tableauArcs = [[NSMutableArray alloc] initWithObjects:s1s2,s1s3,nil];<br /><br />// maintenant qu'ils sont rajoutés aux tableaux et qu'on en a fini avec eux, on peut releaser :<br />[s1 release]; [s2 release]; [s3 release]; // nos sommets<br />[s1s2 release]; [s1s3 release]; // nos arcs<br />// NB: faudra pas oublier de releaser tableauSommets et tableauArcs dans le -(void)dealloc bien sûr<br /><br />...<br />...<br />...<br /><br />// pour l'exemple, si tu veux rajouter un sommet en cours de route :<br />Sommet* s4 = [[Sommet alloc] initWithName:@"D"];<br />[tableauSommets addObject:s4];<br />[s4 release];<br /><br />// et pour rajouter un arc entre le sommet B et D de distance 7 :<br />Sommet* sB = [tableauSommets objectAtIndex:1]; // tels qu'on les as ajoutés, le sommet A est en zero, le B en 1<br />Sommet* sD = [tableauSommets objectAtIndex:3]; // et le D en 3 (on aurait pu utiliser la variable s4 aussi on l'a pas encore releasée)<br />[tableauArcs addObject:[[[Arc alloc] initWithDistance:7 fromSommet:sB toSommet:sD] autorelease]];<br />// et voilà , on a récupéré nos deux sommets et on a créé un arc entre eux
ton (float)dist c'est juste le poids de l'arc hein? Et apres dans le initWithDistance je trace une ligne des coordonnée (s1.x;s1.y) -> (s2.x,s2.y) .
Dans mon initWithName de sommet je dois aussi rajouter tout ce qui est coordonnée du sommet, couleur etc.. Et je mois j'ai tout mis en void, je voulais savoir ce que ça allait changer de mettre les méthodes en id. Merci en tout cas j'avais pas pensé a faire comme ca ... ::)
ton (float)dist c'est juste le poids de l'arc hein? Et apres dans le initWithDistance je trace une ligne des coordonnée (s1.x;s1.y) -> (s2.x,s2.y) .
Oui, c'était l'idée
dans 1238563314:
Dans mon initWithName de sommet je dois aussi rajouter tout ce qui est coordonnée du sommet, couleur etc..
Oui tout à fait, j'ai oublié les coordonnées des sommets, qu'il faut bien sûr rajouter en variable d'instance de ta classe Sommet, et rajouter un constructeur de commodité (ou pas) qui te permet de passer ces coordonnées (tu peux aussi rajouter une [tt]@property NSPoint position[/tt] et affecter la valeur à cette position dans la ligne d'après le init quand tu crées ton sommet, si tu veux pas avoir un constructeur de commodité qui a un nom de 3km)
Mais bon c'était pour l'exemple, j'allais pas tout te faire non plus, c'était juste pour te donner une idée de la vision du modèle... que tu sembles avoir compris si tu me fais cette remarque donc :P
dans 1238563314:
Et je mois j'ai tout mis en void, je voulais savoir ce que ça allait changer de mettre les méthodes en id.
Alors par contre si tu crées réellement un constructeur de commodité (initXXX), il y a des règles à respecter : comme tu vas l'appeler sous la forme [tt]s = [[Sommet alloc] initXXX][/tt] il faut que la méthode init retourne un (id), et il faut aussi avoir appelé [super init] au début de ta méthode. Je t'invite à relire la doc à ce sujet ici, en bref il faut toujours coder ses designed initializers ainsi :
-(id)initXxx:(Type)var Yyy:(Type2)var2<br />{<br />Â if ((self = [super init])) {<br />Â Â // code spécifique ici qui va initialiser les variables d'instance d'après var et var2<br />Â }<br />Â return self;<br />}
Merci en tout cas j'avais pas pensé a faire comme ca ... ::)
Bah heu c'est la base de la POO, tu crées des classes représentant les objets que tu vas manipuler, et tu crées des instances de ces classes pour créer les objets. Il faut mieux voir tout ce que tu veux manipuler comme des objets. Il va falloir t'habituer à avoir cette vision, ça viendra avec la pratique, et au final on réalise que c'est plus clair, on peut manipuler des sommets individuellement, des arcs aussi, ça finit par faire un code clair et propre à lire.
Après en plus tu peux rajouter des méthodes que tu appellerais genre "-(void)drawSommet:(Sommet*)s" et "-(void)drawArc:(Arc*)arc" à ta partie vue qui vont se charger du dessin d'un sommet individuel et d'un arc individuel, et il te suffira pour ton dessin final das drawRect de boucler sur tous tes sommets de ton tableau pour appeler drawSommet dessus, et tous tes arcs pour appeler drawArc.
NB : On pourrait imaginer aussi plutôt une méthode [tt]-(void)draw[/tt] à mettre dans la class Sommet, qui dessine se dernier, et pareil pour Arc. Mais ça ne respecterai pas le MVC, car là où tes Sommet et Arc décrivent ton Modèle, le draw fait partie de la partie Vue, donc faut mieux séparer les 2 composantes.
Ok merci je vais me pencher dessus sérieusement. Pour les methodes de dessin j'avais bien fait comme ca mais je mettait en paramettre un context. Ce n'est pas a faire là ? Le context se trouvera dans ma méthode alors..
J'ai tester déjà avec juste la classe Sommet. Ca marche, j'initialise à un sommet, ca l'affiche bien. Par contre si je veux en faire plusieurs, j'ai mis une boucle for pour afficher ensuite tous mes sommets
Je voulais savoir s'il fallait release temp à chaque itération ... En tout cas c'est cool, j'avais pas pensé à faire tout ça de cette manière et c'est bien plus pratique.
T'as beaucoup de mal avec la gestion mémoire quand même :P Pourquoi constamment faire des allocations / releases à chaque dessin ? Il faut allouer les sommets et arcs une fois pour toute à la lecture du fichier, point barre.
Le mac va me faire une case mémoire pouvant contenir mon temp et donc commet je reitere l'oépération je n'ai pas besoin de release car a chaque fois la mémoire demandée par mon temp ne changera pas. C'est ça ?
Le mac va me faire une case mémoire pouvant contenir mon temp et donc commet je reitere l'oépération je n'ai pas besoin de release car a chaque fois la mémoire demandée par mon temp ne changera pas. C'est ça ?
Non le alloc crée un nouvel espace en mémoire pour contenir ton objet, certes, mais une fois que l'objet existe quelque part, tant qu'il est retenu par au moins un objet, il existe encore en mémoire. Par contre si tous ceux qui l'ont "retain" ont fini par le "releaser", et que du coup la balance retain-release (qu'on appelle retainCount) est retombée à zéro, là plus personne ne dit vouloir utiliser ton objet, donc il est détruit.
On compare souvent ça à un chien en laisse. Le alloc/init crée ton chien, et lui ajoute une laisse (c'est l'objet qui a fait le alloc/init qui tient ton chien en laisse). Ensuite quand des objets font un retain (explicite, genre toi qui appelle un retain, ou implicite, genre tu mets ton "chien" dans une collection comme NSArray ou NSDictionary qui comme dit dans la doc retain les objets qu'ils contiennent), ce retain correspond à l'ajout d'une laisse à ton chien. Et quand on fait un release, explicite (appel à release) ou implicite (suppression de l'objet du tableau dans lequel il était par ex), ça enlève la laisse au chien. Quand plus personne ne tient le chien en laisse, il est libre de s'enfuir, plus personne n'en a plus rien à fouttre de lui (ouais c'est cruel). Du coup il est détruit de la mémoire (et le runtime appelle alors sa méthode "dealloc" tout seul sur cet objet)
Là c'est pareil, tu crées un Sommet au début de ton programme (quand tu lis ton fichier), donc il a un retainCount de 1 (une seule "laisse"). Puis tu le mets dans un tableau, qui le retient implicitement (le retainCount = nombre de "laisses" passe à 2). Du coup tu peux relâcher la variable qui t'a servi à créer ton Sommet avant de l'ajouter à ton tableau, puisqu'il est encore retenu dans ton tableau. Et tant que tu ne le supprimes pas de ton tableau (ou que tu n'envoyes pas un release à ton tableau, ce qui envoie un release à tous ses éléments aussi), ton Sommet existe encore, puisqu'il est dans le tableau.
// initialisation, lecture du fichier<br />// ajout d'un sommet au tableau : on le crée, le temps de l'ajouter, et on le release<br />Sommet* s = [[Sommet alloc] initWith...]; // retainCount = 1<br />[tableauSommets addObject:s]; // retainCount à 2 car retenu par le tableau<br />[s release]; // retainCount retombe à 1<br />// ton sommet existe encore, dans le tableau<br /><br />...<br /><br />// Récupération du sommet stocké dans le tableau<br />Sommet* temp = (Sommet*)[tableauSommets objectAtIndex:0];<br />// pas besoin de faire un alloc/init/release ici, on récupère un Sommet déjà existant dans le tableau<br /><br />// boucle pour dessiner tous les Sommets de ton tableauSommet<br />for(Sommet* s in tableauSommets)<br />{<br />Â [self drawSommet:s];<br />}
Du coup il est détruit de la mémoire (et le runtime appelle alors sa méthode "dealloc" tout seul sur cet objet)
T'es sûr que c'est le runtime qui gère ça ? Il me semblerait plus logique que ça soit l'appel à "release" de NSObject qui teste s'il est à 0 et appelle "dealloc" le cas échéant ???
Du coup il est détruit de la mémoire (et le runtime appelle alors sa méthode "dealloc" tout seul sur cet objet)
T'es sûr que c'est le runtime qui gère ça ? Il me semblerait plus logique que ça soit l'appel à "release" de NSObject qui teste s'il est à 0 et appelle "dealloc" le cas échéant ???
Ouais ho tu vas pas commencer à pinailler lol Une petite faute sur un post de 3km, ça va hein :P Bon ok allez, hop je t'offre un pour me faire pardonner
Ouais en effet c'est très certainement NSObject qui se charge d'appeler dealloc, d'autant plus que la gestion du retainCount avec les méthodes retain/release & co sont propres à NSObject... mais ce que je voulais dire c'est que c'est pas à nous d'appeler "dealloc" quoi
Par contre c'est bizar, j'ai réimplémenter mes méthodes de mouvement de sommet. Ca marche bien mais mes arcs ne bougent plus. J'ai eu l'idée de faire une boucle qui regarde quel arc est connecté au sommet sélectionné et alors de lui attribuer les coordonnée de mon sommet bougeant mais si j'ai plusieurs arc je suis out .
Bah si enfin je pense, vu que dans les parametre init d'un arc je mets le sommet d'arrivé et de départ. Pourtant rien ne bouge. J'ai encore du mal faire un truc...
Mais, mais... Pourquoi dupliquer ces variables d'instances ? C'est pas ça qu'il faut faire, il faut avoir deux pointeurs vers Sommet et les conserver, c'est tout !
Bah non je débute en objet car en cours on voit le C. La POO c'est en 3eme année :-\\ . Et comme j'e nai marre de dev en C en cours pour regarder a la console comment est mon graphe j'ai décider de me plonger sur ca en Objective-C et par la même occasion prendre un peu d'avance sur l'année prochaine. Pas de la tarte ...
Si tu gardes des références sur les sommets, tu n'as rien d'autre à faire, les coordonnées que tu récupéreras via ces références seront toujours OK. Tandis que si tu copies les coordonnées, il faudra que tu les mettes à jour à chaque déplacement, et non seulement c'est dramatiquement complexe, mais en plus c'est pas optimisé du tout !
Réponses
Bah... désolé, mais très certainement si ! :P
Comme un appel à la fonction dessin avant que tout ne soit correctement initialisé par exemple...
C'est un soucis au niveau graphique pur ou niveau coordonnées de l'arc ?
à‰trange cette idée de tableau de tableaux ; moi j'aurais fait un tableau unique qui contient pour chaque arc la référence des 2 sommets.
Et apres dans le initWithDistance je trace une ligne des coordonnée (s1.x;s1.y) -> (s2.x,s2.y) .
Dans mon initWithName de sommet je dois aussi rajouter tout ce qui est coordonnée du sommet, couleur etc..
Et je mois j'ai tout mis en void, je voulais savoir ce que ça allait changer de mettre les méthodes en id.
Merci en tout cas j'avais pas pensé a faire comme ca ... ::)
Mais bon c'était pour l'exemple, j'allais pas tout te faire non plus, c'était juste pour te donner une idée de la vision du modèle... que tu sembles avoir compris si tu me fais cette remarque donc :P
Alors par contre si tu crées réellement un constructeur de commodité (initXXX), il y a des règles à respecter : comme tu vas l'appeler sous la forme [tt]s = [[Sommet alloc] initXXX][/tt] il faut que la méthode init retourne un (id), et il faut aussi avoir appelé [super init] au début de ta méthode. Je t'invite à relire la doc à ce sujet ici, en bref il faut toujours coder ses designed initializers ainsi :
Bah heu c'est la base de la POO, tu crées des classes représentant les objets que tu vas manipuler, et tu crées des instances de ces classes pour créer les objets. Il faut mieux voir tout ce que tu veux manipuler comme des objets. Il va falloir t'habituer à avoir cette vision, ça viendra avec la pratique, et au final on réalise que c'est plus clair, on peut manipuler des sommets individuellement, des arcs aussi, ça finit par faire un code clair et propre à lire.
Après en plus tu peux rajouter des méthodes que tu appellerais genre "-(void)drawSommet:(Sommet*)s" et "-(void)drawArc:(Arc*)arc" à ta partie vue qui vont se charger du dessin d'un sommet individuel et d'un arc individuel, et il te suffira pour ton dessin final das drawRect de boucler sur tous tes sommets de ton tableau pour appeler drawSommet dessus, et tous tes arcs pour appeler drawArc.
NB : On pourrait imaginer aussi plutôt une méthode [tt]-(void)draw[/tt] à mettre dans la class Sommet, qui dessine se dernier, et pareil pour Arc. Mais ça ne respecterai pas le MVC, car là où tes Sommet et Arc décrivent ton Modèle, le draw fait partie de la partie Vue, donc faut mieux séparer les 2 composantes.
Pour les methodes de dessin j'avais bien fait comme ca mais je mettait en paramettre un context. Ce n'est pas a faire là ? Le context se trouvera dans ma méthode alors..
Je voulais savoir s'il fallait release temp à chaque itération ...
En tout cas c'est cool, j'avais pas pensé à faire tout ça de cette manière et c'est bien plus pratique.
Pourquoi constamment faire des allocations / releases à chaque dessin ?
Il faut allouer les sommets et arcs une fois pour toute à la lecture du fichier, point barre.
Le mac va me faire une case mémoire pouvant contenir mon temp et donc commet je reitere l'oépération je n'ai pas besoin de release car a chaque fois la mémoire demandée par mon temp ne changera pas. C'est ça ?
On compare souvent ça à un chien en laisse. Le alloc/init crée ton chien, et lui ajoute une laisse (c'est l'objet qui a fait le alloc/init qui tient ton chien en laisse). Ensuite quand des objets font un retain (explicite, genre toi qui appelle un retain, ou implicite, genre tu mets ton "chien" dans une collection comme NSArray ou NSDictionary qui comme dit dans la doc retain les objets qu'ils contiennent), ce retain correspond à l'ajout d'une laisse à ton chien. Et quand on fait un release, explicite (appel à release) ou implicite (suppression de l'objet du tableau dans lequel il était par ex), ça enlève la laisse au chien.
Quand plus personne ne tient le chien en laisse, il est libre de s'enfuir, plus personne n'en a plus rien à fouttre de lui (ouais c'est cruel). Du coup il est détruit de la mémoire (et le runtime appelle alors sa méthode "dealloc" tout seul sur cet objet)
Là c'est pareil, tu crées un Sommet au début de ton programme (quand tu lis ton fichier), donc il a un retainCount de 1 (une seule "laisse"). Puis tu le mets dans un tableau, qui le retient implicitement (le retainCount = nombre de "laisses" passe à 2). Du coup tu peux relâcher la variable qui t'a servi à créer ton Sommet avant de l'ajouter à ton tableau, puisqu'il est encore retenu dans ton tableau. Et tant que tu ne le supprimes pas de ton tableau (ou que tu n'envoyes pas un release à ton tableau, ce qui envoie un release à tous ses éléments aussi), ton Sommet existe encore, puisqu'il est dans le tableau.
T'es sûr que c'est le runtime qui gère ça ?
Il me semblerait plus logique que ça soit l'appel à "release" de NSObject qui teste s'il est à 0 et appelle "dealloc" le cas échéant ???
Ouais en effet c'est très certainement NSObject qui se charge d'appeler dealloc, d'autant plus que la gestion du retainCount avec les méthodes retain/release & co sont propres à NSObject... mais ce que je voulais dire c'est que c'est pas à nous d'appeler "dealloc" quoi
http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html
J'ai eu l'idée de faire une boucle qui regarde quel arc est connecté au sommet sélectionné et alors de lui attribuer les coordonnée de mon sommet bougeant mais si j'ai plusieurs arc je suis out .
Pour le moment ca me parait correct . Mes ar et dep sont des variables d'instance.
Mais ensuite dans ma méthode drawArc dans la classe NSView je fait :
En gros là ca ne trace plus rien.
C'est pas ça qu'il faut faire, il faut avoir deux pointeurs vers Sommet et les conserver, c'est tout !
Tu as déjà fait du développement objet ? :P
Et comme j'e nai marre de dev en C en cours pour regarder a la console comment est mon graphe j'ai décider de me plonger sur ca en Objective-C et par la même occasion prendre un peu d'avance sur l'année prochaine.
Pas de la tarte ...
Tandis que si tu copies les coordonnées, il faudra que tu les mettes à jour à chaque déplacement, et non seulement c'est dramatiquement complexe, mais en plus c'est pas optimisé du tout !