[résolu] NSColor: Problème de retain?
Rocou
Membre
Bonjour,
Mon application plante et je ne sais pas pourquoi. Je suppose que c'est un problème de release/retain mais je ne sais pas comment résoudre cela. J'ai eu exactement le même problème avec une NSDate.
Voici le topo:
Je veux dessiner des carrés de couleur dans une vue.
J'ai une classe Toto qui ne contient une variable NSColor.
Dans initWithFrame,
Je créée une instance de Toto, j'initialise son instance NSColor avec une couleur puis j'ajoute cet objet dans un tableau ([totoArray addObject:monToto])
et je release mon objet.
(je répète l'opération dans une boucle certain nombre de fois)
Puis dans drawRect,
Je créée une instance de Toto, j'initialise son instance NSColor avec le premier élément de mon tableau totoArray et je dessine mon premier carré avec pour couleur [monToto couleur]
Je répète l'opération autant de fois qu'il y a d'éléments dans le tableau.
ça fonctionne mais quand j'essaie, par exemple, d'agrandir ma fenêtre, ça plante.
Ci-joint un mini projet.
Mon application plante et je ne sais pas pourquoi. Je suppose que c'est un problème de release/retain mais je ne sais pas comment résoudre cela. J'ai eu exactement le même problème avec une NSDate.
Voici le topo:
Je veux dessiner des carrés de couleur dans une vue.
J'ai une classe Toto qui ne contient une variable NSColor.
Dans initWithFrame,
Je créée une instance de Toto, j'initialise son instance NSColor avec une couleur puis j'ajoute cet objet dans un tableau ([totoArray addObject:monToto])
et je release mon objet.
(je répète l'opération dans une boucle certain nombre de fois)
Puis dans drawRect,
Je créée une instance de Toto, j'initialise son instance NSColor avec le premier élément de mon tableau totoArray et je dessine mon premier carré avec pour couleur [monToto couleur]
Je répète l'opération autant de fois qu'il y a d'éléments dans le tableau.
ça fonctionne mais quand j'essaie, par exemple, d'agrandir ma fenêtre, ça plante.
Ci-joint un mini projet.
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Tu récupères un NSColor via la méthode ColorValueForHex:.
Cet objet NSColor n'étant pas créé via un alloc/init/new/copy, donc il s'agit d'un objet en autorelease pool.
Tu enregistres cet objet dans un objet de ta classe toto.
Mais comme il n'y a aucun retain fait sur ce NSColor, il est donc susceptible d'être purgé de la mémoire à tout moment.
Modifie le @property *couleurToto de ta classe Toto en y enlevant assign et en le remplaçant par retain.
Merci, ça confirme ce que je soupçonnais.
Hélas, cela ne change rien du tout
je remplace:
return [NSColor colorWithDeviceRed:c1/255.0 green:c2/255.0 blue:c3/255.0 alpha:1];
par
return [NSColor redColor];
Pas de plantage. C'est à n'y rien comprendre.
je vais manipuler des NSString et les convertir selon les besoins.
EDIT: bon, ça ne fonctionne pas davantage :-\\
En fait, dés qu'il s'agit d'objet, ça plante.
- Tu appelles la méthode -init de Toto, que tu n'as pas définie, c'est donc l'implémentation de NSObject qui est appelée. A priori, pas de problème puisque les variables d'instance sont initialisées à zéro.
- Ensuite tu appelles initToto:, qui n'est pas une méthode d'init, mais un équivalent de setCouleurToto: (pourquoi ne pas appeler celle-ci ?), mais sans retain (c'est mal).
- Il manque une méthode -dealloc:
Les méthodes redColor et compagnie renvoient un singleton qui ne sera donc jamais désalloué -> pas de plantage.
(d'ailleurs [tt]NSLog(@retainCount: %d , [[NSColor redColor] retainCount]);[/tt] pourrait nous donner plus d'infos, quoique je me méfie quand même de ce genre de test)
Du coup ça pourrait expliquer pourquoi avec [tt]redColor[/tt] ça ne plante pas alors qu'avec [tt]colorWithDeviceRed:green:blue:alpha:[/tt] ça plante, si tu fais un release de trop sur ta couleur retournée : un release sur une constante n'ayant aucun effet (no-op)
Oui mais j'ai écris ce petit projet à -la-va-vite pour illustrer mon problème.
Tu as bien sûr raison sur la rigueur à laquelle il faudrait que je m'astreigne mais tout ceci ne résout pas mon problème
La solution est-elle ici? Comment faire ce 'retain'? A quel niveau du code?
Faudrait-il que je code moi-même un 'singleton'?
N'y-a-t-il pas un moyen de faire en sorte que certains objets ne soient jamais releasés?
Ce que je ne comprends pas, c'est que je stocke tout dans un tableau. Comment le contenu des objets peut-il disparaà®tre? Le tableau ne stocke que des pointeurs sur des objets?
Bon, je vais finir par utiliser des types C...
Assign
le @synthesize couleur; est équivalent au code suivant:
-> On conserve seulement une référence vers newCouleur. Si newCouleur est désallouée et qu'on tente d'y accéder => plantage.
Retain
le @synthesize couleur; est équivalent au code suivant:
-> On conserve la référence sur la nouvelle couleur, et on incrémente son retainCount. => Il faut libérer la mémoire occupée par couleur dans -dealloc.
Céroce ton message est très clair et je t'en remercie, cela confirme ce que j'avais parfaitement compris (pour une fois). Cependant, si tu reprends mon code et que tu le modifies comme tu viens de me l'écrire, ça plante toujours autant.
EDIT: ha ok, comme ça, c'est mieux
Ouf, ça fonctionne, merci!
Et mon ancien problème de NSDate est résolu également