Incomprehension avec un NSMutableArray

feebeling

Membre confirmé
20 Juin 2009
10
0
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
:
Bloc de code:
-(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:

Bloc de code:
-(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:

Bloc de code:
-(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
 
Deux choses déjà qui me paraissent bizarre en regardant ton code rapidement (je dis pas que ça résoudra ton problème):

Bloc de code:
            Film *film = [[Films alloc]init];
euh, Film ou Films la classe, ou y'a une astuce ?


Bloc de code:
    for(int i = 1; i< [filmsTab count] ; i++)
       {
        [[filmsTab objectAtIndex:i] displayFilm];
    }
L'index i devrait pas commencer à zéro ?
 
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)addFilmToList:(NSString *)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
 
Tout d'abord, dans init, le plus simple est de faire:
Bloc de code:
-(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:
Bloc de code:
-(NSString*) description
{
	return [NSString stringWithFormat:@"%@ nom: %@ auteur: %@",[super description],[self nom],[self auteur]];
}
 
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):

Bloc de code:
- (IBAction)addFilm:(id)sender{

	[media addFilmToList:[txtName stringValue] :[txtAuthor stringValue]];
	[media displayAllFilms];
	
	[txtName setStringValue:@""]; 
	[txtAuthor setStringValue:@"" ];
	
}
 
Ca serait merveilleux :D.

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

Bloc de code:
-(void)setName:(NSString *)n{
	name = n;
}
-(void)setAuthor:(NSString *)n{
	author = n;
}
 
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 :
Bloc de code:
-(void)setName:(NSString *)n{
        [n retain];
        [name release];
	name = n;
}
 
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)
Bloc de code:
-(void)setName:(NSString *)n{

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

Et bien sûr tu as pensé à la méthode dealloc: :siffle:
Bloc de code:
-(void) dealloc
{
  [name release];
  [author release];
  [super dealloc];
}

[grillé à cause de la tempête, ma connexion est très instable]
 
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 :D).
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.
 
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.
 
  • J’aime
Réactions: Human-Fly
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 :zen: