2011-05-16 2 views
0

@interface:notation Dot, la libération et dealloc

UIImageView *myImageView; 

@property (nonatomic, retain) UIImageView *myImageView; 

@implementation:

@synthesize myImageView; 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    self.myImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)]; 
} 

Quel est le nombre de référence pour myImageView? 2 (1 à partir de alloc, 1 à partir de la notation point conserver) ou 3 (1 à partir de alloc, 1 à partir de la conservation de points, 1 à @property retain)

Ces deux instructions ont-elles le même nombre de références?

self.myImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)]; 

et

myImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)]; 

De plus, je suppose que vous les libérer dans @implemenation et méthode dealloc, correcte?


EDIT:

Je n'ai pas la réponse que je voulais, peut-être ma question est vague. Je comprends la notation par points, @property, @synthesize, et comment fonctionne setter et getter. Ce que je ne comprends pas, c'est ce qui arrive quand on utilise soi-même. et sans "moi". concernant le nombre de retenues. J'ai réellement couru la méthode retainCount sur l'objet myImageView et cela confirme mon original, le "self". cas a un nombre de retenue de deux sur le chauve-souris (avec alloc et propriété conservent donc c'est probablement une bonne idée d'utiliser autorelease là). Maintenant, cela conduit à une autre question, si je ne devais pas utiliser autorelease, comment puis-je faire à ce sujet? libérer une fois dans viewDidLoad et une fois de plus dans dealloc entraînerait toujours une fuite de mémoire, non?

self.myImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)]; 
NSLog(@"retain count dot: %d", [myImageView retainCount]); 

2011-05-17 10: 01: 14,915 test [1249: 207] retenir le nombre de points: 2

myImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)]; 
NSLog(@"retain count: %d", [myImageView retainCount]); 

2011-05-17 10: 03: 14,715 test [1278: 207 ] nombre de retenue: 1

+1

Ne considérez pas les valeurs de retenue comme des valeurs absolues; pensez-y comme des deltas. C'est à dire. "' alloc' donne un objet w/compte de référence +1 "," 'self.myImageView = aView' ajoute un au nombre de références", "' release' décrémente le nombre de retenue par un "..... – bbum

+0

@bbum , compris, mais ce que j'essaie de saisir, ce sont les différences lors de l'utilisation de l'évaluateur de la propriété et ivar directement. Est-ce que je dois encore libérer les deux dans viewDidLoad (puisque j'alloue là-bas), et le relâcher à nouveau dans dealloc parce que c'est une propriété retain. – s2000coder

+2

Comptez les retenues que vous causez et équilibrez chacune d'elles avec un dégagement; '+ alloc 'est un, l'affectation à la propriété via le setter est une autre ... donc, oui, vous avez besoin de deux versions ou autoreleases. C'est aussi simple que ça Si vous conservez, vous devez libérer. – bbum

Répondre

2

Premièrement: vous ne devez faire aucune hypothèse sur le nombre de références. Ce sera trompeur au mieux.

Si vous utilisez l'accès à la propriété (self.myImageView = ...), il sera automatiquement conservé, ce qui entraîne la fuite de l'UIImageView dans viewDidLoad. Vous devez utiliser quelque chose comme

self.myImageView = [[[UIMageView alloc] init.... ] autorelease]; 

Votre exemple (sans accès « point ») modifiera le Ivar directement, il ne fuira pas cette nouvelle instance. MAIS il fuira l'ancien imageView que vous remplacez si vous ne le libérez pas avant.

Je recommande fortement d'utiliser l'accès à la propriété tout le temps.Et ne pas oublier de nettoyer dans dealloc:

[myImageView release], myImageView = nil; 

Certaines personnes préfèrent self.myImageView = nil; mais cela peut avoir des effets secondaires.

+0

Pour le premier cas utilisant l'accès à la propriété, je devrais le libérer dans viewDidLoad et dans dealloc, non? (puisque le compte de référence est 2). Et pour le second cas, je n'ai pas besoin de le libérer dans viewDidLoad et juste dans la méthode dealloc? C'est là que je suis confus. – s2000coder

+0

Fondamentalement oui. Mais la syntaxe à points libère aussi les anciens objets correctement - c'est vraiment recommandé. En outre, vous pouvez utiliser self.myImageView = nil; dans viewDidUnload mais c'est une question différente. Le guide de programmation de gestion de mémoire est une très bonne lecture. – Eiko

1

non, ils ne sont pas identiques. Le premier "retient", augmentant ainsi le nombre de références. Donc, soit vous l'assignez d'abord à une variable temporaire, puis vous relâchez (dans le premier cas) [sinon, ajoutez 'autorelease' et sortez sans variable temporaire], ou vous vérifiez qu'il n'y a pas déjà d'imageView assignée (et s'il y a - le relâcher) dans le second cas.

+0

self.myImageView = alloc ... et [myImageView release] dans viewDidLoad est le même que myImageView = alloc ... et [myImageView release]? .... et relâcher une fois de plus dans la méthode dealloc? – s2000coder

+0

Désolé si mon commentaire ci-dessus n'était pas clair. Ce que je voulais dire, c'est que dans les deux cas, vous devez toujours sortir deux fois, n'est-ce pas? – s2000coder

0

Pour ajouter à la première réponse, le système de notation de points prend soin de la gestion de la mémoire impliquée avec la libération de l'ancien objet et la conservation du nouveau. Dans le second cas vous auriez une énorme fuite de mémoire potentielle sur vos mains, puisque chaque fois que cela est appelé, la retenue augmente de 1. Ce n'est pas le cas avec le setter de notation par points.

Puisqu'il conserve l'objet, vous devez cependant libérer l'allocation d'origine.

Questions connexes