# Incomprehension avec un NSMutableArray



## feebeling (27 Février 2010)

Bonjour, ça fait maintenant quelques mois que j'apprends l'objective C et donc je bloque sur les NSMutableArray. Je veux que mon programme stock des objets dans un tableau, j'ai donc utilisé un NSMutableArray. L'insertion des objets fonctionne parfaitement, le problème survient lorsque je tente de récupérer mes objets stockés dans le tableau. Pour expliquer voici mon code:

J'ai une classe Medias qui contient un tableau d'objets Films.

Initialisation du NSMutableArray contenant des objets de type Films dans le init de ma classe Medias
:

```
-(id) init{
	
	if (self = [super init]){

	        Film *film = [[Films alloc]init];
		filmsTab = [[NSMutableArray alloc] initWithObjects: film, nil];
		[filmsTab retain];
		[film release];
	}
	return self;
}
```

Methode de ma classe Medias permettant d'ajouter des objets films:


```
-(void)addFilmToList:(NSString *)n :(NSString *)a{
	
	Film *film = [[Films alloc]init];
	[film setName: n];
	[film setAuthor: a];
	[filmsTab addObject: film];
	[film release];
	
}
```

Methode de ma classe Medias permettant d'afficher le contenu du tableau d'objets Films:


```
-(void)displayAllFilms{
	
	NSLog(@ "nombre de films dans la list: %d\n",[filmsTab count]);
	
	for(int i = 1; i< [filmsTab count] ; i++)
       {
	    [[filmsTab objectAtIndex:i] displayFilm];
	}
}
```

La méthode addFilmToList est appelée lorsque je clique sur un bouton de mon IHM. J'ai l'impression que la méthode objectAtIndex modifie le contenu du tableau. Je m'explique, lors de l'ajout du premier élément le contenu du tableau est le suivant:   

index 0 -> *Films
index 1 -> *Films

J'affiche alors le contenu du tableau cela fonctionne. Je regarde ensuite le contenu du tableau avec le debugger et là surprise j'obtiens ceci:

index 0 -> *Films 
index 1 -> *NSObject dont le contenu est isa

Quelqu'un aurait-il une idée de où pourrait être le problème?

Merci


----------



## Diablovic (28 Février 2010)

Deux choses déjà qui me paraissent bizarre en regardant ton code rapidement (je dis pas que ça résoudra ton problème):



feebeling a dit:


> ```
> Film *film = [[Films alloc]init];
> ```


euh, Film ou Films la classe, ou y'a une astuce ?




feebeling a dit:


> ```
> for(int i = 1; i< [filmsTab count] ; i++)
> {
> [[filmsTab objectAtIndex:i] displayFilm];
> ...


L'index i devrait pas commencer à zéro ?


----------



## feebeling (28 Février 2010)

Merci pour ta réponse Diablovic cependant pour le Film *film, c'est une erreur de frappe de ma part, dans mon code c'est bien Films *film. L'indice i commençant à 1 est parce que j'initialisais le NSMutableArray avec un objet film par défaut. Corrigé depuis. Il semblerait que le problème provienne d'un mauvais cast. 
Le fonctionnement du programme est le suivant, dans un windows form j'ai deux NSTextField et un bouton "Add". Je rentre le nom du film dans le premier NSTextField et l'autheur du film dans le second, je clique ensuite sur le bouton Add qui appel une méthode (IBAction) qui s'occupe de récupérer la valeur de ces NSTextField puis d'appeler la méthode "-(void)addFilmToListNSString *)n NSString *)a" qui prend en paramètre le contenu de mes deux NSTextField. Après investigation avec le debugger, je me suis rendu compte que ces deux paramètres "nom du film" et "nom de l'autheur" le type associé change aléatoirement. Par exemple un coup ces paramètres sont du type NSString * un autre coup ils sont NSCFString * (j'ai pas compris à quoi correspondait ce type), enfin c'est vraiment aléatoire et je suis complètement perdu.

Merci


----------



## mpergand (28 Février 2010)

Tout d'abord, dans init, le plus simple est de faire:

```
-(id) init{
	
	if (self = [super init]){

		filmsTab = [[NSMutableArray alloc] initWithCapacity:10];
	}

	return self;
}
```

NSCFString ou NSString c'est la même chose.

Pour vérifier le contenu de ton tableau de films, tu peux faire:
NSLog(@"%@", filmsTab);

Encore mieux: si tu ajoutes une méthode description à ta classe film, tu pourra afficher les valeurs de nom et auteur:

```
-(NSString*) description
{
	return [NSString stringWithFormat:@"%@ nom: %@ auteur: %@",[super description],[self nom],[self auteur]];
}
```


----------



## feebeling (28 Février 2010)

Merci, vraiment cool ces tips. La methode description est un peu comme la methode toString en java, c'est bien ça?
Par contre ça ne fonctionne toujours pas, je pense vraiment que le problème ce situe au niveau des NSTextField car lorsque que je remplis mon tableau à la main directement dans le programme ça fonctionne, par contre dès que le tableau est remplit via les NSTextField ça plante.

---------- Nouveau message ajouté à 15h53 ---------- Le message précédent a été envoyé à 15h45 ----------

Pour info voilà comment je recupere les valeurs dans mes NSTextField (txtName et txtAuthor sont les NSTextField):


```
- (IBAction)addFilm:(id)sender{

	[media addFilmToList:[txtName stringValue] :[txtAuthor stringValue]];
	[media displayAllFilms];
	
	[txtName setStringValue:@""]; 
	[txtAuthor setStringValue:@"" ];
	
}
```


----------



## mpergand (28 Février 2010)

feebeling a dit:


> Merci, vraiment cool ces tips. La methode description est un peu comme la methode toString en java, c'est bien ça?


That's it !

Pour les plantages, je pense savoir d'où ça vient, montre ton code pour les méthodes setName/setAuthor.


----------



## feebeling (28 Février 2010)

Ca serait merveilleux .

Voilà mes setters pour les attributs name et author de ma classe Films:


```
-(void)setName:(NSString *)n{
	name = n;
}
-(void)setAuthor:(NSString *)n{
	author = n;
}
```


----------



## ntx (28 Février 2010)

Quand tu places un objet (dans ton cas ta string) dans un autre (ton film), il faut faire un retain dessus, car si ton objet d'origine est détruit (release sur la dernière instance) par ailleurs tu vas perdre l'information dans ton objet contenant.
Il faut te rappeler que ton signe égal dans ton set concerne une égalité d'adresse, tu bosses sur des pointeurs. Tu n'as pas fait une copie du contenu de ta string.
Il y a plusieurs façons de faire dont celle-ci :

```
-(void)setName:(NSString *)n{
        [n retain];
        [name release];
	name = n;
}
```


----------



## mpergand (28 Février 2010)

Gagné !!

Bon, faut que tu relises la gestion mémoire en ObjectiveC, c'est pas compliqué, mais faut en comprendre parfaitement son principe, sinon tu ne t'en sortiras pas.

(méthode alternative à celle de ntx)

```
-(void)setName:(NSString *)n{

	if(name!=n)	
		{				
		[name release];	
		name=[n retain];
		}	
}
```

Et bien sûr tu as pensé à la méthode dealloc: 

```
-(void) dealloc
{
  [name release];
  [author release];
  [super dealloc];
}
```

[grillé à cause de la tempête, ma connexion est très instable]


----------



## feebeling (28 Février 2010)

MERCI!!!!! Le problème est résolu. J'ai galéré dessus pendant 2 semaines (je ne fais pas que ca de mes journée quand même ). 
Je pensais avoir compris la gestion mémoire en objective C.... il faut croire que non, je vais me replonger dans mes cours.

Encore merci vous m'enlever une sacré épine du pied.


----------



## Bladrak (1 Mars 2010)

Sinon si tu veux t'éviter les getters/setters (s'ils n'ont pas de traitements spéciaux à faire à ce moment là) tu peux utiliser les versions "auto-générées".

Dans ton .h tu mets un @property (nonatomic, retain) Type *var; et dans ton .m un @synthesize var;
A partir de là le compilateur te génère les getters/setters associés à ta variable de classe, que tu peux invoquer avec monObjet.var.


----------



## feebeling (1 Mars 2010)

Merci pour l'astuce ça peut être utile.


----------



## ntx (1 Mars 2010)

Certes mais avant d'utiliser ce genre de truc apprend à bien maîtriser le langage, c'est indispensable pour comprendre ce que font les outils automatiques


----------



## feebeling (1 Mars 2010)

Pour être honnête je ne suis pas adepte de tout ce qui est automatique je préfère savoir ce que je fais.


----------

