Vois ça comme des "alias" si ça peut t'aider, comme dans le Finder.
Quand schlum te parle de "il ne faut pas copier les variables d'instances, mais juste pointer dessus", tu peux comparer, si tu avais par exemple un document texte sur ton disque dur, à "quand tu as besoin d'avoir aussi une référence à ce fichier autre part, dans un autre dossier, il ne faut pas faire une copie de ce fichier, mais plutôt un alias".
En effet, pour reprendre la comparaison, si tu fais une copie de ton fichier A à un autre emplacement, ce seront des fichiers distincts : si tu modifies l'un, cela ne va pas modifier l'autre, qui a sa vie indépendante. Alors que si tu fais un alias, ça ne fait que "pointer" vers l'original. Si tu modifies l'original, bah quand tu vas double-cliquer sur l'alias qui est à l'autre endroit ça va ouvrir l'unique document, celui-la même que tu as modifié.
Oui en effet j'y vois plus claire avec cette image d'alias. Et quelle est la différence entre la méthode "forte" de Schlum et celle qu'il propose avant?
Oui en effet j'y vois plus claire avec cette image d'alias. Et quelle est la différence entre la méthode "forte" de Schlum et celle qu'il propose avant?
La référence " forte " est plus Cocoa, et garantit que les références seront toujours valables (c'est comme si on mettait une laisse aux instances tant qu'on en a besoin). La référence " faible ", c'est plus C++ et demande une gestion plus consciencieuse de la mémoire.
J'ai envie de pouvoir sauvegarder le model d'un graphe construit et de pouvoir le recharger par la suite. Par quel moyen il faudrait passer pour pouvoir sauvegarder tout le graphe ? Un fichier .txt ? XML ? Autres moyens ?
Bon j'avance dans mes algos et là je bloque sur un truc tout bête je pense. J'ai besoin de la matrice de continuité du graphe.
Exemple :
J'ai trois noeuds "A", "B" et "C" .
A -> B poids 1. A -> C poids 3. C -> B poids 2.
La matrice associée serait :
013 000 020
Pour moi c'est juste une histoire de tableau. Je parcours mon premier tableau qui contient mes sommets. En double boucle je parcours mon tableau d'arcs. Pour chaque sommet je parcours ce tableau d'arcs en regardant si le nom de mon sommet correspond au nom "départ" de mon arc. SI c'est le cas je marque le poids sinon je marque 0.
J'ai fais comme ça .
<br />-(void)matrice<br />{<br /> <br /> /* tableau à double entrée */<br /> int **tab= NULL;<br /> tab = (int **)malloc([tableauSommets count]*sizeof(int*));<br /><br /> <br /> for( int i=0 ; i<[tableauSommets count]; i ++)<br /> {<br /> tab[i] = (int*)malloc([tableauArcs count]*sizeof(int));<br /> Sommet *s = [tableauSommets objectAtIndex:i];<br /> <br /> for(int j = 0; j<[tableauArcs count]; j ++)<br /> {<br /> Arc *a = [tableauArcs objectAtIndex:j];<br /> <br /> /* si je suis sur la diagonale c'est un sommet pointant sur lui meme donc pas d'arc possible */<br /> if(i == j)<br /> {<br /> tab[i][j] = 0;<br /> }<br /> <br /> /* sinon si mon nom de sommet est le même que le nom de départ d'un arc*/<br /> else if([s.nom isEqualToString:a.de]) <br /> {<br /> tab[i][j] = a.poids;<br /> }<br /> <br /> /* si ce n'est pas le cas je mets 0 */<br /> else<br /> {<br /> tab[i][j] = 0;<br /><br /> }<br /> <br /> <br /> }<br /><br /> }<br />}<br />
s.nom est le nom de ton sommet a.de est j'imagine une variable de type Sommet* qui pointe vers le sommet de départ... donc ce n'est pas une NSString.
De plus tant qu'à faire plutôt que de comparer les noms des sommets, autant comparer les sommets eux-mêmes : [tt]if (a.de == s)[/tt] ou [tt]if ([a.de isEqualTo:s])[/tt].
Si a.de est de type sommet. C'est une variable de ma classe Arc qui récupère le nom de sommet de départ rentré comme paramètre d'initialisation de mon arc.
Hum en effet pour ta remarque Shlum ... mais il me faudrait une sorte d'étiquette interne de type entiere pour chaque sommet pour connaitre sa position d'ajout et donc se place dans la matrice. Non?
Hum en effet pour ta remarque Shlum ... mais il me faudrait une sorte d'étiquette interne de type entiere pour chaque sommet pour connaitre sa position d'ajout et donc se place dans la matrice. Non?
Oui, bien sûr... La seule chose qui m'étonne c'est qu'elle n'y soit pas déjà :P
Et pourquoi copier dans "de" et "vers" le nom de tes sommets ? Tu reproduis ici l'erreur que tu avais faite avec la position de tes sommets que tu stockais dans les arcs alors que tu peux les avoir dans tes sommets.
Si tu veux le nom du sommet de départ d'un arc, il faut faire monarc.d.nom (et pas avoir une variable de et faire monarc.de) : en effet, si après coup tu changes le nom de ton sommet dans ton instance d'un Sommet*, tous les arcs qui ont se sommet en tant que point de départ (ou d'arrivée) garderont pourtant dans ta variable "de" (ou "vers") l'ancien nom du sommet !
A la limite si tu veux vraiment garder "de" et "vers", fais-en propriétés readonly dont tu implémentes l'accesseur pour qu'il retourne le nom du sommet... mais calculé en temps réel, et non stocké en dur, pour que s'il change dans le Sommet*, ça soit bien le nouveau que l'on retourne.
@interface Arc : ...<br />{<br /> ...<br /> // pas besoin de variable "NSString* de;"<br /> // ni de "NSString* vers;" ici !!<br />}<br />// ici on déclare qu'on peut utiliser "monarc.de" comme si c'était une property<br />// mais on ne va pas l'associer à une variable d'instance comme tu le fais toi<br />@property(nonatomic, readonly) NSString* de;<br />@property(nonatomic, readonly) NSString* vers;<br />@end<br /><br />@implementation Arc<br />// ici du coup on va pas laisser "@synthesize de, vers;" qui générerait l'accesseur de ces variables<br />// en utilisant la variable d'instance, puisqu'on ne fait plus avec ça<br />// à la place, on définit nous-même l'accesseur associé à la @property :<br />-(NSString*)de { return d.nom; } // on retourne le nom du sommet de départ, calculé en temps réel<br />-(NSString*)vers { return a.nom; } // pareil pour le sommet d'arrivée<br />@end
Hum en effet pour ta remarque Shlum ... mais il me faudrait une sorte d'étiquette interne de type entiere pour chaque sommet pour connaitre sa position d'ajout et donc se place dans la matrice. Non?
Oui, bien sûr... La seule chose qui m'étonne c'est qu'elle n'y soit pas déjà :P
Oui bon rooo ^^. Merci Ali je crois que je vais faire monArc.d.nom pour pas avoir 36000 variables.
J'ai commencé à essayer NSKeyedArchiver. Je tatonne un peu. SI j'ai bien compris il faut que je transforme mes objets (Sommets et Arcs) en code binaire. J'ai modifier un code et au départ j'ai ça :
Non, dans les fonctions qui vont enregistrer / ouvrir un fichier... Le "initForWritingWithMutableData", c'est juste un "init" avec un NSMutableData vide, un constructeur quoi ???
Bon ca marche super et mon dijkstra aussi ^^. J'ai pensé pouvoir supprimé les sommet un à un en appuyant sur un bouton d'édition qui affiche sur chaque sommet une petite croix (un peu comme sur l'iphone). Pour ca je dois rajouter un parametre dans ma fonction d'init de sommet ou bien créer un tableau de NSView ? J'aurai penché pour la premiere solution et ainsi en fonction d'un état BOOL dessiner ou non l'image dans mon drawRect .
Ni l'un ni l'autre... Soit c'est une propriété qui s'applique à un seul élément, soit à tous, mais il serait illogique de l'avoir sur seulement un sous-ensemble de taille > 1.
La solution du flag me semble mieux... mais en effet à ne mettre que sur ta UIView (appellons-là GraphView) qui te sert à dessiner ton graphe (celle pour qui le drawRect consiste essentuellement à appeller [self drawSommet:...] sur chaque sommet et [self drawArc:...] sur chaque arc).
Du coup au moment de dessiner tes sommets, si le "editable" de ta GraphView est à YES tu dessines la petite croix à côté du sommet quand tu le dessines, sinon non. Et de même quand tu détectes les clics dans ta GraphView, si editable est à YES tu fais le traitement adéquat (détecter si le clic est sur une zone où il y a une petite croix, si oui supprimer le sommet correspondant du graphe (et ses arcs associés) et redessiner le graphe... Sinon bah pourquoi pas permettre d'autres types d'édition, par exemple un clic sur le nom du sommet pour modifier son nom, ou un drag du sommet pour le déplacer dans le dessin... et puis si le clic est dans le vide bah l'ignorer.
Réponses
Par exemple là je l'ai modifier et j'ai fait ça :
x1,x2,y1,y2,poids étant mes variables d'instance.
C'est pas encore ça ?
Là ca trace bien mais si je bouge un sommet il n'y a pas d'actualisation.
Quand schlum te parle de "il ne faut pas copier les variables d'instances, mais juste pointer dessus", tu peux comparer, si tu avais par exemple un document texte sur ton disque dur, à "quand tu as besoin d'avoir aussi une référence à ce fichier autre part, dans un autre dossier, il ne faut pas faire une copie de ce fichier, mais plutôt un alias".
En effet, pour reprendre la comparaison, si tu fais une copie de ton fichier A à un autre emplacement, ce seront des fichiers distincts : si tu modifies l'un, cela ne va pas modifier l'autre, qui a sa vie indépendante.
Alors que si tu fais un alias, ça ne fait que "pointer" vers l'original. Si tu modifies l'original, bah quand tu vas double-cliquer sur l'alias qui est à l'autre endroit ça va ouvrir l'unique document, celui-la même que tu as modifié.
Si ça peut t'aider à y voir plus clair...
La référence " forte " est plus Cocoa, et garantit que les références seront toujours valables (c'est comme si on mettait une laisse aux instances tant qu'on en a besoin).
La référence " faible ", c'est plus C++ et demande une gestion plus consciencieuse de la mémoire.
Effectivement, ça ne passerait pas la compilation.
J'espere qu'en pratiquant ça va rentrer...
Un fichier .txt ? XML ? Autres moyens ?
J'ai besoin de la matrice de continuité du graphe.
Exemple :
J'ai trois noeuds "A", "B" et "C" .
A -> B poids 1.
A -> C poids 3.
C -> B poids 2.
La matrice associée serait :
013
000
020
Pour moi c'est juste une histoire de tableau.
Je parcours mon premier tableau qui contient mes sommets. En double boucle je parcours mon tableau d'arcs. Pour chaque sommet je parcours ce tableau d'arcs en regardant si le nom de mon sommet correspond au nom "départ" de mon arc. SI c'est le cas je marque le poids sinon je marque 0.
J'ai fais comme ça .
Vous voyez un truc qui va pas?
a.de est j'imagine une variable de type Sommet* qui pointe vers le sommet de départ... donc ce n'est pas une NSString.
De plus tant qu'à faire plutôt que de comparer les noms des sommets, autant comparer les sommets eux-mêmes : [tt]if (a.de == s)[/tt] ou [tt]if ([a.de isEqualTo:s])[/tt].
Hum en effet pour ta remarque Shlum ... mais il me faudrait une sorte d'étiquette interne de type entiere pour chaque sommet pour connaitre sa position d'ajout et donc se place dans la matrice. Non?
Oui, bien sûr... La seule chose qui m'étonne c'est qu'elle n'y soit pas déjà :P
Tu reproduis ici l'erreur que tu avais faite avec la position de tes sommets que tu stockais dans les arcs alors que tu peux les avoir dans tes sommets.
Si tu veux le nom du sommet de départ d'un arc, il faut faire monarc.d.nom (et pas avoir une variable de et faire monarc.de) : en effet, si après coup tu changes le nom de ton sommet dans ton instance d'un Sommet*, tous les arcs qui ont se sommet en tant que point de départ (ou d'arrivée) garderont pourtant dans ta variable "de" (ou "vers") l'ancien nom du sommet !
A la limite si tu veux vraiment garder "de" et "vers", fais-en propriétés readonly dont tu implémentes l'accesseur pour qu'il retourne le nom du sommet... mais calculé en temps réel, et non stocké en dur, pour que s'il change dans le Sommet*, ça soit bien le nouveau que l'on retourne.
Oui bon rooo ^^.
Merci Ali je crois que je vais faire monArc.d.nom pour pas avoir 36000 variables.
J'ai fais ça et ça a l'air de marcher ^^
Je tatonne un peu.
SI j'ai bien compris il faut que je transforme mes objets (Sommets et Arcs) en code binaire.
J'ai modifier un code et au départ j'ai ça :
C'est un début correct?
Mais tu peux faire plus simple sans...
Encoding
- Créer une instance NSMutableData
- Créer un NSKeyedArchiver
- Lui envoyer ce qu'on veut encoder
- Terminer l'encoding
- à‰crire son objet NSData dans un fichier
Decoding
- Initialiser un NSData avec le fichier
- Initialiser un NSKeyedUnarchiver avec
- Récupérer ses objets
Sinon, en rendant son objet Data conforme <NSCoding> :
L'id a envoyer est un sommet de mon tableau de sommet?
Par contre pour :
data correspond à quoi?
Et ces méthodes je dois les implétanter dans ma NSView, c'est bien ça?
Le "initForWritingWithMutableData", c'est juste un "init" avec un NSMutableData vide, un constructeur quoi ???
Sinon dans quel format de fichier ca va enregistrer? C'est à moi de choisir?
C'est du XML binaire (compressé)...
Si tu veux un autre format, alors il va falloir écrire toi même ta classe de sérialisation / désérialisation.
J'ai pensé pouvoir supprimé les sommet un à un en appuyant sur un bouton d'édition qui affiche sur chaque sommet une petite croix (un peu comme sur l'iphone). Pour ca je dois rajouter un parametre dans ma fonction d'init de sommet ou bien créer un tableau de NSView ? J'aurai penché pour la premiere solution et ainsi en fonction d'un état BOOL dessiner ou non l'image dans mon drawRect .
Qu'en pensez-vous?
Soit c'est une propriété qui s'applique à un seul élément, soit à tous, mais il serait illogique de l'avoir sur seulement un sous-ensemble de taille > 1.
À partir de là , c'est une propriété globale.
Du coup au moment de dessiner tes sommets, si le "editable" de ta GraphView est à YES tu dessines la petite croix à côté du sommet quand tu le dessines, sinon non. Et de même quand tu détectes les clics dans ta GraphView, si editable est à YES tu fais le traitement adéquat (détecter si le clic est sur une zone où il y a une petite croix, si oui supprimer le sommet correspondant du graphe (et ses arcs associés) et redessiner le graphe...
Sinon bah pourquoi pas permettre d'autres types d'édition, par exemple un clic sur le nom du sommet pour modifier son nom, ou un drag du sommet pour le déplacer dans le dessin... et puis si le clic est dans le vide bah l'ignorer.