stringByAppendingString: plantage de l'app
Re-bonjour!
Je reviens assez rapidement suite à un autre problème, dans ma petite app de test, j'essaie de concaténer deux strings dans une seule variable et ensuite de l'afficher dans un label.
Jusqu'à maintenant l'affichage dans le label de n'importe quel variable contenant une string n'a pas posé de problème, par exemple:
Aucun problème, le texte s'affiche bien dans le label, mais si je fait ceci:
Le simulateur iphone se bloque.
Si vous pouvez m'aider... :why?:
Je reviens assez rapidement suite à un autre problème, dans ma petite app de test, j'essaie de concaténer deux strings dans une seule variable et ensuite de l'afficher dans un label.
Jusqu'à maintenant l'affichage dans le label de n'importe quel variable contenant une string n'a pas posé de problème, par exemple:
message=[[NSString alloc] initWithFormat:@"Hello world!"];<br />labelmsg.text=message;<br />
Aucun problème, le texte s'affiche bien dans le label, mais si je fait ceci:
message=[[NSString alloc] initWithFormat:@"Hello world!"];<br />message=[message stringByAppendingString:@"et le monde lui répondit merde"];<br />labelmsg.text=message;
Le simulateur iphone se bloque.
Si vous pouvez m'aider... :why?:
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
En fait c'est dans un if et les autres possibilités ont le texte contenant les variables entrées par l'utilisateur
Ton code pose problème:
-[NSString stringByAppendingString] renvoie une nouvelle chaà®ne. La première reste donc en mémoire sans être jamais désallouée. Par contre, je ne comprends pas pourquoi ça plante.
(Et Ceetix a raison, c'est bizarre d'utiliser initWithFormat:, quand on ne lui passe pas une chaà®ne de formattage).
Je manque clairement de bases, la j'essaie de me les faire par moi même en attendant ^^
Maintenant j'utilise initWithString pour la chaine ne devant pas contenir de variables, ça fonctionne tout aussi bien, donc je me coucherais moins bête.
Au sujet du problème précis, tu dis que la première reste en mémoire, mais à part le fait que ça ne soit pas super optimisé ça ne devrait pas faire planter, si?
A coté de ça si je ne fait que concaténer les strings sans les afficher dans le label tout fonctionne, c'est lorsque je lui passe la variable message que ça plante.
Merci de votre aide en tout cas, je patauge un peu, mais je vais y arriver ^^
Essaie avec NSMutableString
Est-ce vraiment sur labelMsg.text = message; que ça plante ?
À vérifier au débogueur.
Comme la nouvelle chaà®ne renvoyée par -[NSString stringByAppendingString:] est autoreleasée, elle sera libérée à la fin du cycle du runtime et message ne pointera plus sur rien.
Le cycle du runtime? c'est à dire?
Au plus j'en apprend au plus je me rend compte de mon ignorance
Et vu que j'ai en général plus de facilité en commençant par la pratique et en apprenant le reste sur le tas, c'est un peu dur vu que les tutoriels bien fait pour l'objective-c sont un peu moins courant que pour les autres langages ^^
Sinon au final j'ai fait ça:
Ca fonctionne nickel, mais je ne sais pas si c'est "propre"
Enfin disons que appendWithString est fait pour ça donc tu devrais l'utiliser.
J'ai essayer ton code chez moi il passe sans souci, je pense que ça viens d'ailleurs (c'est comme la vérité ^^)
Mais quand bien même, il y a quand même un problème de fuite de mémoire.
J'ai donc plutôt essayer ceci:
Sauf que les NSString* reste en mémoire! C'est délire, elle s'affiche quand bien même j'ai fait un release dessus! Si quelqu'un comprends...
ça marche, mais si je ne m'abuse, tu as une belle fuite mémoire sur le premier message.
En gros la variable message référence un objet NSString initialisé avec  @Hello world. Or lorsque tu fais la ligne suivante :
message ne référence plus @Hello World mais un nouvel object NSString étant la recopie de message et de message2.
ça ne plante pas mais le premier @Hello world risque de rester dans la mémoire "ad vitam eternam" à moins que tu n'utilise le ramasse miettes...
[EDIT] oups grilled... par un gars de l'IFSIC en plus... ;-)
Il me semble que quand tu fais un release sur une variable, elle n'est pas détruite immédiatement, de plus si tu ne fais pas message = nil ou final = nil l'adresse reste dans la variable qui ne sera détruite qu'à la fin de la procédure.
Il y a un forum " Débutants : les bases d'Objective-C & Cocoa "
De plus, appeler "release" sur une variable NE met PAS cette variable à nil ! Cela détruit la variable (enfin l'objet sur lequel elle pointe plus exactement), du moins si personne d'autre n'a fait un retain dessus entre temps, mais la variable ne pointe pas sur nil après cela, elle pointe toujours sur le même espace mémoire, c'est juste que du coup cet espace mémoire n'est plus valide après ça.
Avec cet exemple de code ça va sans doute planter car va essayer d'accéder à l'objet qui est à l'adresse mémoire pointée par la variable t, mais autant avant il y avait l'objet Toto à cet endroit, autant maintenant il n'y a plus rien... donc il risque d'essayer d'interpréter ce qu'il y a à cet endroit de la mémoire comme un objet alors que ça risque de plus être ça du tout.
Il se peut que ce code fonctionne quand même et affiche l'objet Toto parce que cet emplacement mémoire pointé par t a été marqué comme étant supprimé, autorisant à ce qu'on écrase l'emplacement mémoire à tout moment puisqu'il n'est plus utilisé... mais si gros coup de bol on n'a pas écrasé cet objet entre temps (et ça on en a aucune garantie), il se peut que le NSLog fonctionne et ne plante pas, mais bon...
Pour revenir sur stringByAppendingString, l'idéal est de bien différencier ses variables pour pouvoir les gérer indépendemment et pas risquer qu'une ancienne écrase une nouvelle : On n'appelle pas release sur msg2 car on ne l'a pas créé avec alloc/initWithString, on a directement utilisé une chaà®ne constante. On n'aura pas besoin de faire de release sur message car on a utilisé un constructeur de commodité stringXXX (stringByAppendingString) qui est équivalent à alloc+init+autorelease.
Après il y a un sacré paquet de méthodes pour concaténer des chaà®nes : utiliser stringByAppendingString de NSString, utiliser une seule NSMutableString et lui rajouter ton msg2 à la fin, utiliser initWithFormat:@%@%@, ... il n'y a pas une solution unique. Par contre selon la solution que tu choisis faut être cohérent et respecter les règles de gestion de mémoire indiquées dans la doc Apple (c'est à dire si c'est toi qui crée l'objet avec alloc, copy, mutableCopy... c'est à toi de faire le release (ou autorelease)" et de même "si tu fais un retain sur un objet, c'est aussi à toi de faire le release (ou autorelease)", mais dans les autres cas (si tu n'as pas appelé alloc, *copy, retain) tu n'as pas à appeler release)
D'où le conseil d'acheter le fameux bouquin d'Aaron Hillegass. Toutes les bases y sont justement expliquées de façon très didactiques. D'ailleurs, le livre répond à 80% des questions posées dernièrement sur ce forum.
ça fait au moins 20 fois qu'Ali essaie d'expliquer rapidement la gestion mémoire, il n'a pas l'air de s'en lasser (?), moi si. C'est pour cela que j'ai fais exprès d'introduire des termes techniques dans ma réponse, qui sont des notions simples une fois lus les premiers chapitres du livre !
Parce que je dévelope pour l'iphone à la base je n'ai pas l'utilité actuellement de déveloper sur mac, mais j'ai voulu aller trop vite sans doute
J'ai eu une entrée d'argent imprévue, le livre est commandé, je vais commencer par le commencement, merci encore pour la référence du bouquin.
Merci à tous pour votre aide, je reviendrais quand j'aurais quelques bases de plus
Sinon amuses toi bien avec ce bouquin, moi je ne l'ai pas encore fini mais il est vraiment super! A bientôt
Voilà :P
Et puis ça m'agace les " Parce que je dévelope pour l'iphone à la base je n'ai pas l'utilité actuellement de déveloper sur mac "
C'est p'têt con, mais pour savoir développer sur iPhone, il faut savoir développer sur Mac, ce sont les même bases.
:-* :-* :-*