# listes chaînées en Objective-C



## boulifb (20 Juin 2007)

Bonjour tout le monde,

Après recherches, j'aimerais savoir s'il existe une classe qui va bien en Objective-C qui gère les liste simplement et/ou doublement chaînées.

J'ai été surpris de ne pas retrouver cette structure dans la section consacrée aux collections dans le CoreFoundation, à moins que ce soit dans une autre framework...

Cordialement.

Fred.


----------



## p4bl0 (20 Juin 2007)

boulifb a dit:


> Bonjour tout le monde,
> 
> Apr&#232;s recherches, j'aimerais savoir s'il existe une classe qui va bien en Objective-C qui g&#232;re les liste simplement et/ou doublement cha&#238;n&#233;es.
> 
> ...


C'est pas un truc du genre NSDictionary (je dis peut-&#234;tre une connerie hein, je connais pas vraiment Cocoa ^^) la classe pour les liste ?

Apr&#232;s pour le truc de doublement cha&#238;n&#233;es (je sais pas du tout ce que c'est), &#231;a doit pouvoir y &#234;tre ajouter en sous classant NSDictionary si ce n'est pas d&#233;j&#224; inclus.


----------



## jb_jb_fr (20 Juin 2007)

Pourquoi s'embeter avec des listes chainées

Tu as la classe NSMutableArray qui te permet de gérer des tableaux d'objets.
Cette classe te permet:
- de connaitre le nombre d'objet
- de prendre l'objet d'index précédent
- de prendre l'objet d'index suivant
- de retirer n'importe quel objet dans la liste
- d'insérer un objet dans la liste à l'endroit que tu veux.
-...

Je pense qu'avec ça tu peux faire tout ce que tu veux.
Il y a même la possibilité de faire du tri ascendant/descendant

Jacques


----------



## Eul Mulot (20 Juin 2007)

Comme l'a dit jb_jb_fr, c'est une des solutions très pratique pour faire une liste, de plus l'expension/réduction de la taille du tableau se fait dynamiquement, l'insertion d'un élément en index 5 va décaller les autres automatiquement et idem pour le retrait d'un objet.


----------



## boulifb (20 Juin 2007)

@p4b10. Non!! NSDictionary ne r&#233;pond pas &#224; ma demande. Merci quand m&#234;me 

@jb_jb_fr et eul mulot
Merci pour la solution concr&#232;te, je vais regarder la classe NSMutableArray. Le but du jeu est  d'avoir une structure similaire &#224; une liste cha&#238;n&#233;e (simplement ou doublement peu importe).

J'essaye d&#233;sesp&#233;rement de trouver la classe qui va bien pour lire un fichier et son contenu binaire, puis de charger certaines donn&#233;es dans une liste cha&#238;n&#233;e mais avec les classes Cocoa en Objective-C. Y a pas un &#233;quivalent de CFile quelque part en Objective-C???

C'est gal&#232;re de ne pas conna&#238;tre Cocoa


----------



## ntx (20 Juin 2007)

Pour ranger les données d'un fichier dans un arbre : les classes XML devrait faire l'affaire. Mais si ton fichier n'est pas en XML (et  je suppose que c'est le cas :rateau: ) il va falloir te taper le parsing "à la main" mais ce n'est pas rédhibitoire.


----------



## p4bl0 (20 Juin 2007)

boulifb a dit:


> @p4b10. Non!! NSDictionary ne répond pas à ma demande. Merci quand même



 de rien 

:rose:


----------



## Mala (21 Juin 2007)

Comme ça vu de loin, j'aurais tendance à dire:
1) lire le fichier binaire avec une classe NSData.
2) sous réserve de connaître la structure binaire, récupérer les données via getBytes de NSData.
3) stocker les données dans un NSMutableArray qui rend obsolète l'utilisation d'une liste chaînée.


----------



## Mala (21 Juin 2007)

p4bl0 a dit:


> Après pour le truc de doublement chaînées (je sais pas du tout ce que c'est)


Pour le côté culturel, une liste chaînée permet de parcourir une liste d'objet via des conteneurs (en générale une simple structure C) qui encapsule l'objet ainsi qu'un pointeur vers le conteneur suivant. On parle de double chaînage lorsqu'on dispose aussi d'un pointeur vers l'objet précédant Donc:

Chaînage simple -> je parcours ma liste du début vers la fin uniquement.
Chaînage double -> je parcours ma liste dans les deux sens.

Avec un NSArray/NSMutableArray, le problème ne se pose plus puisque pour parcourir la collection d'objets il suffit de passer en revue le tableau.


----------



## p4bl0 (21 Juin 2007)

Mala a dit:


> Pour le côté culturel, une liste chaînée permet de parcourir une liste d'objet via des conteneurs (en générale une simple structure C) qui encapsule l'objet ainsi qu'un pointeur vers le conteneur suivant. On parle de double chaînage lorsqu'on dispose aussi d'un pointeur vers l'objet précédant Donc:
> 
> Chaînage simple -> je parcours ma liste du début vers la fin uniquement.
> Chaînage double -> je parcours ma liste dans les deux sens.
> ...


Merci


----------



## boulifb (21 Juin 2007)

Merci pour les infos.
Je vais essayer ça ce midi.

Pour le contenu du fichier, il doit être lu binaire (fopen avec l'otion "rb"). Pour ce qui est de la signification de chacun des octets, pas de problème. Je sais ce qu'ils contiennent et comment les analyser. Je veux juste refaire la lecture du contenu du fichier en Objective-C avec les classes Cocoa. L'histoire de me familiariser avec le langage 

Dans cette optique, je m'amuse à refaire un jeu que j'avais écrit sous Windows en C ANSI via Allegro mais cette fois-ci en sous Mac OS X en Objective-C et Allegro (oui, ça tourne sur mac en natif via Cocoa et Quartz). Comme Allegro mixe C et Objective-C (pour la partie fenêtrage), normalement, je dois pouvoir aussi mixer les deux architectures dans mon jeu.

Fred.


----------



## boulifb (21 Juin 2007)

Bon, j'ai essay&#233; ne serait-ce que d'ouvrir le contenu d'un fichier en Cocoa et l&#224;, c'est la cata... J'ai bien parcouru la doc d'Apple (BinaryData.pdf et NSData_class.pdf) et fait comme dans l'exemple, mais rien n'y fait. J'ai d&#251; louper un &#233;pisode...

Voici le programme:

```
#import <Foundation/Foundation.h>
 
#define SAFE_RELEASE(p)         { if (p) { [p release]; p=NULL; } }
 
int main(int argc, char** argv)
{
 NSString* fileName="Volumes/Data/Projects/objc/FF01"; // normalement il y a un @ apr&#232;s le =
 NSData*  fileContent=[NSData dataWithContentsOfFile: fileName];
 
 SAFE_RELEASE(fileContent);
 SAFE_RELEASE(fileName);
 return 0;
}
```
 
NB: Normalement, il y a un @ apr&#232;s le = et fileName est bien cr&#233;&#233;... Normalement, faut tester si fileName est bon avant d'appeler dataWithContentsOfFile, mais bon, l&#224;, c'est un exemple 

Voici la sortie:

```
2007-06-21 14:00:13.371 level[852] *** _NSAutoreleaseNoPool(): Object 0x304a30 of class NSCFString autoreleased with no pool in place - just leaking
2007-06-21 14:00:13.372 level[852] *** _NSAutoreleaseNoPool(): Object 0x3032a0 of class NSConcreteData autoreleased with no pool in place - just leaking
```
Si quelqu'un a une id&#233;e... C'est le bienvenue.

Cordialement.

Fred.


----------



## Mala (21 Juin 2007)

Alors commen&#231;ons par le commencement. Objective-C et cocoa en g&#233;n&#233;ral fonctionne avec des "autorelease pool" qui permettent de s'affranchir dans certaines conditions de la gestion m&#233;moire. Chaque thread (dans ton cas ton main est le thread principal) doit disposer dau moins un pool qui va stocker et g&#233;rer les objets autorelease.

L&#224; tu vas me dire:"mais je fais tout moi m&#234;me".

Oui mais non, en appelant par exemple dataWithContentsOfFile tu utilises ce que l'on appel un constructeur de commodit&#233; qui te retourne un objet allou&#233; en mode autorelease (c'est comme &#231;a que fonctionne la plupart des constructeurs de commodit&#233.

Du coup le programme pense qu'il y a une perte m&#233;moire car tu as cr&#233;&#233; un objet qui n'est associ&#233; &#224; aucun pool.

Donc pour r&#233;soudre ce probl&#232;me:
Ajoute en tout d&#233;but du main:

```
NSAutoreleasePool *pool = [NSAutoreleasePool new];
```

Et &#224; la fin du code en toute derni&#232;re ligne:

```
[pool release];
```

Et l&#224; &#231;a plante encore. Pourquoi?

Et bien tout simplement parce que ta macro SAFE_RELEASE n'a pas de raison d'&#234;tre sur des objets qui sont autorelease. Au contraire, tu vas lib&#233;rer les objets et derri&#232;re ton pool va essayer de faire de m&#234;me et patatra.

Deux solutions:
- Soit tu supprimes l'appel &#224; ta macro.
- Soit en tant que programmeur consciencieux tu ne l'entend pas de cette oreille et tu veux avoir tout pouvoir sur les objets que tu alloues dans ton code. Dans ce second cas, tu ajouteras le code suivant apr&#232;s la cr&#233;ation de tes objets:


```
[fileName retain];
    [fileContent retain];
```
Et l&#224; pour faire simple, tu indiques &#224; l'autorelease pool qu'il est bien mignon mais que jusqu'&#224; preuve du contraire c'est toi le boss et que les objets tu te les lib&#232;res toi m&#234;me. 

Toujours tr&#232;s perspicace, tu me r&#233;torques alors : "Quel est alors l'int&#233;r&#234;t des objets g&#233;r&#233;s en autorelease???"
Et bien imagines un objet dont l'utilisation est partag&#233;es par plusieurs autres objets (ex: une ressource genre une image jpeg). Lequel des objets &#224; le droit de supprimer l'espace m&#233;moire allou&#233; par l'objet image s'il n'en a plus besoin? Dur dilemme. :hein:  Et l&#224; le mode autorelease prend tout son int&#233;r&#234;t.   On passe l'objet image en tant qu'objet autorelease aux autres objets. Chaque objet qui veut conserver l'image fait alors un retain dessus et cela incr&#233;mente un compteur associ&#233; &#224; notre ressource. Une fois qu'un objet ne veux plus garder la ressource, il fait un release sur l'objet image. Lorsque le compteur arrive a z&#233;ro, plus personne n'utilise l'image alors l'objet se lib&#232;re.


----------



## boulifb (21 Juin 2007)

Wizzzz &#231;a marche!

Dans mon cas, les ressources ne sont pas partag&#233;es. En effet, les fichiers que je vais &#234;tre amen&#233; &#224; manipuler sont sp&#233;cifiques au jeu.

Finalement, l'autorelease est &#224; Cocoa ce que le Garbage Collector est &#224; .NET si j'ai bien compris. On cr&#233;&#233; ses objets en m&#233;moire et lorsque la vie de l'objet est termin&#233; l'architecture se charge de n&#233;ttoyer le tout. Avec ces explications, &#231;a va d&#233;j&#224; mieux.  

J'ai donc bien loup&#233; un &#233;pisode dans les docs d'Apple. C'est que je voulais mettre les mains dans le camboui moi 

Donc, en Objective-C via Cocoa, lorsque l'on utilise les constructeurs de commodit&#233; de classe, il vaut mieux utiliser la m&#233;thode retain plut&#244;t que release. En revanche, si on utilise la m&#233;thode init l&#224;, il faut bien utiliser la m&#233;thode release. C'est bien &#231;a?

NB: &#224; tout hasard, sous Xcode, comment on cr&#233;&#233; une application en ligne de commande en Objective-C? En gros, ce que j'ai fais avec vi, j'aimerais le refaire sous Xcode. Je pense que &#231;a doit &#234;tre faisable


----------



## Mala (21 Juin 2007)

boulifb a dit:


> Dans mon cas, les ressources ne sont pas partag&#233;es. En effet, les fichiers que je vais &#234;tre amen&#233; &#224; manipuler sont sp&#233;cifiques au jeu.


Et tu n'as pas des objets qui partagent des donn&#233;es communes dans ton jeux (ex: un jeu de dame o&#249; on pourrait imaginer avoir autant d'instances que de pions mais une seule image pour les pions blanc et une seule image pour les pions noir)? Enfin, bref c'&#233;tait pour te pr&#233;senter le principe.



boulifb a dit:


> Finalement, l'autorelease est &#224; Cocoa ce que le Garbage Collector est &#224; .NET si j'ai bien compris. On cr&#233;&#233; ses objets en m&#233;moire et lorsque la vie de l'objet est termin&#233; l'architecture se charge de n&#233;ttoyer le tout. Avec ces explications, &#231;a va d&#233;j&#224; mieux.


En fait parler de Garbage Collector est un raccourci un peu rapide. En gros avec un GC, lorsque tu lib&#232;res un objet, la lib&#233;ration m&#233;moire se fera au bon vouloir du GC (d'o&#249; parfois des engorgements m&#233;moire si la machine est tr&#232;s sollicit&#233;e). Avec le principe d'objective-c, le fonctionnement est d&#233;terministe (on sait exactement &#224; quel moment les objets autorelease sont lib&#233;r&#233;s) contrairement aux langages qui utilisent un GC (Java,.Net,etc). On peut m&#234;me d'ailleurs utiliser des pool interm&#233;diaires dans des boucles faisant de gros traitements.
Exemple:


```
NSAutoreleasePool *poolPrincipal = [NSAutoreleasePool new];

// 
// Ici on peut faire plein de manip avec des objet autorelease
//
NSString *maSuperString = [NSString stringWithString:@"Etpataietpatata"];


// maintenant on passe &#224; la boucle
int patati = 0;
int patata = 10;
for(; patati<patata; patati++)
{
    NSAutoreleasePool *poolSecondaire = [NSAutoreleasePool new];

    //A partir de maintenant tous les objets autorelease sont g&#233;r&#233;s par le
    //pool secondaire

    // Ici on fait de gros traitements et comme on sait pas ce que font les 
    // classes cocoa qu'on j'utilise, il y a sans doute des objets autorelease 
    // qui font grimper la m&#233;moire

    // Enfin, on lib&#232;re le pool pour d&#233;gager tous les objets autorelease qui sont
    // obsol&#232;tes avant la boucle suivante.
    [poolSecondaire release];
}

// On lib&#232;re le pool principal qui va nettoyer les objets autorelease que l'on a
// &#233;ventuellement cr&#233;&#233; en dehors de la boucle. 
[poolPrincipal release];
```
Tout &#231;a pour bien montrer que contrairement au GC, on conserve ici la main mise sur la lib&#233;ration des objets (m&#234;me ceux autorelease). C'est donc plus fin qu'un GC et cela offre de meilleurs performances (pas de latence dans la lib&#233;ration m&#233;moire) car un GC n'aura jamais la qualit&#233; d'appr&#233;ciation d'un d&#233;veloppeur pour savoir exactement quand lib&#233;rer des donn&#233;es qui ne sont plus utiles.

Il est a noter cependant que la prochaine version d'OSX int&#233;grera un GC en compl&#233;ment de la gestion actuelle pour laisser le choix aux programmeurs. Donc pour ceux qui pr&#233;f&#232;rent ce sera dispo avec Obj-C 2.0.



boulifb a dit:


> J'ai donc bien loup&#233; un &#233;pisode dans les docs d'Apple. C'est que je voulais mettre les mains dans le camboui moi


Chaque langage a ses subtilit&#233;s qu'il est important d'int&#233;grer pour pouvoir se concentrer plus sereinement sur son code. Mais c'est vrai que c'est toujours tentant de partir &#224; l'aventure...  



boulifb a dit:


> Donc, en Objective-C via Cocoa, lorsque l'on utilise les constructeurs de commodit&#233; de classe, il vaut mieux utiliser la m&#233;thode retain plut&#244;t que release.


Je pense que tu as voulu dire autorelease au lieu de release? Il est effectivement pr&#233;f&#233;rable de toujours g&#233;rer soit m&#234;me les objets quand c'est possible. Maintenant, si tu as par exemple une m&#233;thode d'une classe qui doit retourner un objet et bien tu le mettras en autorelease pour des raisons de s&#233;curit&#233; (et par respect des conventions). 



boulifb a dit:


> En revanche, si on utilise la m&#233;thode init l&#224;, il faut bien utiliser la m&#233;thode release. C'est bien &#231;a?


Oui tout ce qui est init... sont des constructeurs "simples" qui te retourne l'objet allou&#233; et c'est &#224; toi de d&#233;cider de le basculer ou pas en autorelease. C'est aussi le cas des m&#233;thodes de copies (copy et mutableCopy).


----------



## clampin (22 Juin 2007)

boulifb a dit:


> Wizzzz ça marche!
> NB: à tout hasard, sous Xcode, comment on créé une application en ligne de commande en Objective-C? En gros, ce que j'ai fais avec vi, j'aimerais le refaire sous Xcode. Je pense que ça doit être faisable










C'est très simple tu va dans le menu File->New Project-> là tu choisis Command Line utility ->Foundation tool pour la faire en objective-C ou Standard Tool pour la faire en C.

Bonne découverte de cocoa...

Clampin


----------



## tatouille (23 Juin 2007)

http://developer.apple.com/document...Reference/CFArrayRef/Reference/reference.html

le coreFoundation est en C tu peux utiliser n'importe quelle methode C &#224; l'interieur de l'obj-C

quelques correspondances d'objets

http://developer.apple.com/document...Reference/CFArrayRef/Reference/reference.html

http://developer.apple.com/document...lasses/NSArray_Class/Reference/Reference.html

http://developer.apple.com/documentation/Cocoa/Conceptual/Collections/Articles/Arrays.html

http://developer.apple.com/document...Conceptual/CFCollections/Concepts/common.html


----------



## tatouille (23 Juin 2007)

Mala a dit:


> Et tu n'as pas des objets qui partagent des données communes dans ton jeux (ex: un jeu de dame où ...



obsolète concernant obj-c 2


----------



## Mala (23 Juin 2007)

tatouille a dit:


> obsol&#232;te concernant obj-c 2



Avant de sortir une phrase de son contexte, il est toujours int&#233;ressant de lire jusqu'au bout... 


Mala a dit:


> Il est a noter cependant que la prochaine version d'OSX int&#233;grera un GC en compl&#233;ment de la gestion actuelle pour laisser le choix aux programmeurs. Donc pour ceux qui pr&#233;f&#232;rent ce sera dispo avec Obj-C 2.0.



Donc on y apprend :
1- qu'Obj-C 2.0 n'est pas encore disponible ce qui ne fait pas les affaires de notre ami aujourd'hui, maintenant, tout de suite.
2- qu'Obj-C m&#234;me en 2.0 continuera &#224; &#234;tre compatible avec une gestion autorelease/retain.


----------



## boulifb (24 Juin 2007)

@clampin: ok, j'avais trouvé 

@mala
Par contre sous Xcode, via le débogueur, lorsque j'ouvre mon fichier, le nombre d'octets chargés est le bon (ouf), mais je n'arrive pas à voir en mémoire son contenu. Lorsque je déroule l'objet NSData, il y a un pointeur "isa" et puis c'est tout. Même si je demande à voir le contenu du pointeur, je n'ai pas les bonnes données visiblement. Je ne vois pas où sont stockés les octets lus.

Pour le moment, je commence à me familiariser à l'Objective-C. Pour la version 2, j'attendrais la sortie de Leopard et de Xcode 3... Un jour à la fois. J'ai jusqu'au mois d'Octobre pour me faire les dents. 

Sinon, venant du C/C++/C#, l'Objective-C n'est pas si méchant une fois le nez dedans.

Fred.


----------



## Mala (24 Juin 2007)

boulifb a dit:


> @mala
> Par contre sous Xcode, via le d&#233;bogueur, lorsque j'ouvre mon fichier, le nombre d'octets charg&#233;s est le bon (ouf), mais je n'arrive pas &#224; voir en m&#233;moire son contenu. Lorsque je d&#233;roule l'objet NSData, il y a un pointeur "isa" et puis c'est tout. M&#234;me si je demande &#224; voir le contenu du pointeur, je n'ai pas les bonnes donn&#233;es visiblement. Je ne vois pas o&#249; sont stock&#233;s les octets lus.


En fait, il faut bien int&#233;grer qu'Obj-C est un langage dynamique (les acc&#232;s aux variables d'un objet ou m&#234;me d'une m&#233;thode sont ainsi calcul&#233;s &#224; la vol&#233;e contrairement &#224; des langage statics comme Java ou C++). Mais du coup, tu ne peux pas toujours d&#233;rouler aussi facilement (notamment pour les classes dont tu n'as pas le source) le contenu d'un objet comme tu le ferais avec une instance C++ par exemple. C'est une des sp&#233;cificit&#233;s d'Obj-C qui lui conf&#232;re une grande puissance mais bref on pourra y revenir si tu as des questions.
Pour r&#233;cup&#233;rer ton buffer dans ton cas, utilises la m&#233;thode "bytes".

```
const char *buf = (const char*)[monObjetNSData bytes];
```
la m&#233;thode "bytes" retournant un "const void *", on cast le retour de la m&#233;thode en fonction du format d&#233;sir&#233; (8bits,16bits,sign&#233;, pas sign&#233;, etc) pour &#233;viter un warning.

Tu peux aussi utiliser des m&#233;thodes telles que..

```
- (void)getBytes:(void *)buffer range:(NSRange)range
```
...pour r&#233;cup&#233;rer des copies de portions de ton buffer si tu pr&#233;f&#232;res.

A noter que si tu voulais pouvoir modifier ton buffer (mais je pense pas que ce soit le cas ici), tu te tournerais vers NSMutableData qui dispose d'une m&#233;thode "mutableBytes". Laquelle retourne un "void*" (donc modifiable).

Donc pour la parenth&#232;se, en Obj-C on fait toujours la distinction entre objets "en lecture seule" et objets modifiables. 
Exemple de classes:
NSString et NSMutableString.
NSArray et NSMutableArray.
NSDictionary et NSMutableDictionary.
etc.



boulifb a dit:


> Sinon, venant du C/C++/C#, l'Objective-C n'est pas si m&#233;chant une fois le nez dedans.


Tout a fait. Le tout est d'int&#233;grer les quelques rudiments qui vont bien pour partir du bon pied et apr&#232;s c'est pas sorcier.

Pour parcourir plus rapidement les classes Obj-C qu'avec l'aide d'xcode, je te conseille  l'excellent AppKiDo. Bien s&#251;r au d&#233;but le probl&#232;me c'est qu'il faut savoir ce qu'on cherche  mais tu verras qu'&#224; l'usage sa pr&#233;sentation hi&#233;rarchique des classes et sa recherche rapide sont tr&#232;s pratiques.

Edit: je viens d'y penser mais si tu codes sous PPC, ne pas oublier que la lecture de fichiers binaires peut &#234;tre impact&#233; par l'architecture processeur (tu avais l'air de sous entendre que ton fichier venait d'un PC si je ne m'abuse). Il peut donc y avoir n&#233;cessit&#233; de r&#233;ordonner les octets lus.


----------



## tatouille (24 Juin 2007)

tatouille a dit:


> obsol&#232;te concernant obj-c 2



dsl j'ai r&#233;pondu rapidement c'&#233;tait &#224; prendre comme une note bien sur qu'en obj-c v2 tu peux compiler
en gardant l'option, c'est juste pour quelq'un qui donne comme exemple le cplusplus, et qu'on lui propose un language objet avec des retain et des release (alloc free) cela peut paraitre assez bizarre et assez chiant,  la nouvelle donne : 
 AUTO-MEM qui est bien meilleur que celle du c++ qui parfois peu devenir une horreur , car oui un language qui cache les systemcalls cela peut paraitre + confortable , mais &#224; l'utilisation c'est souvent le contraire , enfin cela d&#233;pend ce que l'on fait , c'est pour cela que je suis devenu un D afficionados



l'OBJ_C pourrait se r&#233;sumer par getElementByID hop un sample tout chaud

PS : je vois que mon nouvel avatar &#224; du succ&#232;s 






 c'est un hommage &#224; la plus belle pair de seins de macg&#233; ( acc&#233;ssoirement elle plonge  en mer chaude, si un jours,  elle est au courant de ce commentaire je saurais que cela vient de l'un d'entre vous car je ne pense pas qu'elle descende aussi profond  )


ca d&#233;pend du PC , si cela provient d'un NIX aucun probl&#232;me there are all bigendian


----------



## Mala (24 Juin 2007)

tatouille a dit:


> dsl j'ai répondu rapidement c'était à prendre comme une note bien sur qu'en obj-c v2 tu peux compiler
> en gardant l'option,


Y a pas de mal. 
C'est le terme "obsolète" qui m'a fait réagir car le raccourci était un peu rapide. Il y a deux raisons majeures à cela:
- Les GC sont loin d'être la solution miracle en terme de performances/gestion des ressources.
- C'était faire un peu vite l'impasse sur les prédécesseurs de Léopards qui sont encore bien présents (et pour cause  ) et qui le resterons encore un petit moment d'où des problèmes de compatibilité.

Donc pour moi, le GC d'Obj-C va rester un choix (tout comme en langage D il me semble) et à ce titre je trouve que c'est une très bonne chose.



tatouille a dit:


> c'est juste pour quelq'un qui donne comme exemple le cplusplus, et qu'on lui propose un language objet avec des retain et des release (alloc free) cela peut paraitre assez bizarre et assez chiant,


Et les new/delete du C++ sont quoi si ce n'est des équivalents aux new/release d'Obj-C? La notion d'autorelease/retain est juste un complément dont la seul alternative en C++ est l'implémentation de callbacks ou de smart pointers (qui a dit chiant?  ) car le C++ offre par défaut une gestion entièrement manuelle.


----------



## tatouille (24 Juin 2007)

Mala a dit:


> Y a pas de mal.
> C'est le terme "obsolète" qui m'a fait réagir car le raccourci était un peu rapide. Il y a deux raisons majeures à cela:
> - Les GC sont loin d'être la solution miracle en terme de performances/gestion des ressources.
> - C'était faire un peu vite l'impasse sur les prédécesseurs de Léopards qui sont encore bien présents (et pour cause  ) et qui le resterons encore un petit moment d'où des problèmes de compatibilité.
> ...



oui avec boost , qui a dit smart 
oui le garbage collector mechanisme est théoriquement le même


----------



## boulifb (25 Juin 2007)

@Mala:
Bon, je viens de faire une premi&#232;re fonction en Objective-C qui fait quelque chose.

Voil&#224; le code:

```
#import <Foundation/Foundation.h>
#define SAFE_RELEASE(p)   { if (p) { [p release]; } }
int main(int argc, char** argv)
{
 NSAutoreleasePool*  pool=[NSAutoreleasePool new];
 NSSttring*  fileName="FF01"; // il faut un arobas apr&#232;s le = pour que &#231;a compile
 NSData*    fileContent=[NSData dataWithContentsOfFile: fileName];
 unsigned char*   bytes=(unsigned char*) [fileContent bytes];
 int    nCol=0, i=-1;
 for (i=0; i<[fileContent length]; i++, nCol++)
 {
  if (nCol > 16)
  {
   nCol=0;
   printf("\n");
  }
  printf("&#37;02x ", bytes[i]);
 }
 
 printf("\n");
 [fileName retain];
 [fileContent retain];
 SAFE_RELEASE(pool);
 return 0;
}
```
 
Bon, l&#224;, j'ai tout mis dans le main 

Il affiche en hexa le contenu du fichier que je charge et c'est bon.
Pour bien faire, faudrait que je trappe les exceptions lors de l'ouverture du fichier et l'allocation des pointeurs, mais c'est pour l'exemple 

Est-ce bien du Cocoa ce que j'ai fais? En tout cas, je commence &#224; piger l'Objective-C. Le tout est de connaitre les classes.

N'y a-t-il pas un moyen plus "Cocoa" ou plus Apple-Like que ce que j'ai fais pour acc&#233;der aux donn&#233;es?

Pour mon code, je dois analyser octet par octet le contenu du fichier qui contient en fait les descripteurs de niveaux (taille du niveau, indexes de tiles, table d'actions etc.) , afin de recr&#233;er en m&#233;moire le niveau dans une structure que j'&#233;crirais en Objective-C.

fred.


----------



## Mala (26 Juin 2007)

boulifb a dit:


> Il affiche en hexa le contenu du fichier que je charge et c'est bon.


Ok, donc pas de souci de plateforme comme je l''&#233;voquais.



boulifb a dit:


> Pour bien faire, faudrait que je trappe les exceptions lors de l'ouverture du fichier et l'allocation des pointeurs, mais c'est pour l'exemple


Cocoa fait un usage assez restreint des exceptions (d'ailleurs la gestion des exceptions Objective-C n'est pas active par d&#233;faut il me semble lorsqu'on cr&#233;er un projet xcode). Ici, il te suffit de tester "fileContent" qui est mit &#224; nil par dataWithContentsOfFile si la lecture se passe mal (tape "dataWithContentsOfFile" dans AppKiDo, tu vas voir il va t'emmener directement dessus...


> Return Value
> A data object by reading every byte from the file specified by path.
> Returns nil if the data object could not be created.


 


> Est-ce bien du Cocoa ce que j'ai fais? En tout cas, je commence &#224; piger l'Objective-C. Le tout est de connaitre les classes.


Ton code marche mais tu as des fuites. 

Quand tu fais &#224; la fin de ton code:

```
[fileName retain];
[fileContent retain];
```
Tu te r&#233;serves la gestion m&#233;moire de ces deux objets. Donc lorsque tu fais le release sur ton pool juste apr&#232;s, il ne s'occupe pas de ces deux lascars. Soit tu supprimes les "retain", soit-tu fais en "release" dessus par la suite (mais dans le cas pr&#233;sent &#231;a n'a pas grand int&#233;r&#234;t. prends le temps de bien relire ce que je t'ai expliqu&#233; dans me post pr&#233;c&#233;dents. Sinon, tu peux aussi jeter un oeil &#224; cet article de Renaud sur la gestion m&#233;moire et qui est tr&#232;s bien fait: Gestion de la m&#233;moire en Objective-C



> N'y a-t-il pas un moyen plus "Cocoa" ou plus Apple-Like que ce que j'ai fais pour acc&#233;der aux donn&#233;es?
> 
> Pour mon code, je dois analyser octet par octet le contenu du fichier qui contient en fait les descripteurs de niveaux (taille du niveau, indexes de tiles, table d'actions etc.) , afin de recr&#233;er en m&#233;moire le niveau dans une structure que j'&#233;crirais en Objective-C.


A premi&#232;re vue, je dirais que c'est d&#233;j&#224; pas mal. Un m&#233;lange d'Obj-C pour le fonctionnel et de C pure pour les performances en ce qui concerne l'acc&#232;s au buffer.

Eventuellement, ce que je ferais perso:
- ajouter une variable genre "int length = [fileContent length]" et l'utiliser dans la boucle. Cela &#233;vite de passer son temps &#224; rappeler une m&#233;thode dont le retour ne change jamais. Le c&#244;t&#233; dynamique d'Obj-C a aussi une contrepartie-> la lenteur des appels de m&#233;thode du fait de l'aiguillage &#224; la vol&#233;e.
- remplacer les printf par des NSLog(). La syntaxe d'utilisation est la m&#234;me (aux caract&#232;res @ pr&#232;s pour indiquer une cha&#238;ne Obj-C mais tu peux en plus tracer des objets Obj-C avec) et &#231;a trace en plus dans le fichier de log.
ex: 

```
NSLog(@"&#37;@",[fileContent description])
```
La m&#233;thode description nous permet ici de demander &#224; l'objet de se d&#233;tailler sous forme d'une cha&#238;ne NSString.

Dans ton cas pour faire exactement la m&#234;me chose que toi, on fait par exemple:

```
NSLog(@"%02x ", bytes[i]);
```


----------



## boulifb (27 Juin 2007)

Salut,

NSLog pour la sortie n'est pas terrible. En effet, il met tout en bloc et met des timestamps lors que j'utilise le formatage %02x.

J'imagine qu'il y a moyen d'avoir l'équivalent du printf en Cocoa.

Sinon, j'ai vu le pourquoi des fuites. "Retain" fait de la rétention de données mémoire, comme son nom l'indique et le pool vide ce qui lui a été donné lors du release si j'ai bien compris.

Maintenant, que j'ai pigé l'Objective-C, reste plus qu'à comperendre l'arcjitecture Cocoa et de prendre mes repères. 

Fred.


----------



## ntx (27 Juin 2007)

Pour les logs il y a le framework log4cocoa, qui reprend le fonctionnement de log4j.


----------



## Mala (27 Juin 2007)

boulifb a dit:


> En effet, il met tout en bloc et met des timestamps lors que j'utilise le formatage %02x.


En effet, je n'avais pas pensé que le timestamps pouvait te gêner. A ma connaissance, il n'y a pas d'équivalent au printf simple en Obj-C. Dans le contexte de Cocoa, les retours utilisateurs sont avant tout graphiques. Lorsqu'on fait des traces texte c'est qu'on veut en garder une trace (d'où la datation des logs).

Mais tu peux néanmoins très bien mélanger les genres pour tes besoins. Voici trois exemples d'équivalences (au timestamps près)...

```
// En C simple
    char buffer [50];
    int n, a=5, b=3;
    n=sprintf (buffer, "%d plus %d is %d", a, b, a+b);
    printf ("[%s] is a %d char long string\n",buffer,n);
    
    // En Objective-C
    NSString *myString = [NSString stringWithFormat:@"%d plus %d is %d", a, b, a+b];
    NSLog(@"[%@] is a %d char long string\n",myString);
    
    // En mélangeant C et Objective-C
    NSString *myString2 = [NSString stringWithFormat:@"%d plus %d is %d", a, b, a+b];
    printf ("[%s] is a %d char long string\n",[myString2 cString],[myString2 length]);
```


----------

