2009-05-09 5 views
2

j'ai un @property qui est défini comme suit:La libération d'un immeuble (Objective-C)

@property (nonatomic, conserver) nom;

Dans une fonction, j'analyse du code XML et définit la propriété name. Ma question est de savoir si je devrais libérer explicitement l'instance conservée précédente avant d'en conserver une nouvelle?

Pour exemple:

myObj.name = [otherObj getName]; // conserver le nombre +1

..

myObj.name = [otherObj getName]; // qui est une nouvelle instance d'un nom, le nom précédent est-il libéré?

Répondre

4

Dans un setter de propriété synthétisé, le code fait quelque chose à peu près analogue à ce (nous aurons name être le nom de la propriété, et _name sera la variable d'instance à auquel il se réfère):

- (void) setName: (NSString *) newValue 
{ 
    if (newValue == _name) 
    return; 

    [newValue retain]; 
    [_name release]; 
    _name = newValue; 
}

Maintenant, cela montre ce qui se passerait en fonction de votre déclaration de propriété ci-dessus. Selon les autres attributs possibles de cette propriété, cette fonction utiliserait soit [newValue copy] au lieu de [newValue retain] (si l'attribut 'copy' était spécifié), soit elle serait enveloppée dans un bloc @synchronized(self) (si l'attribut 'nonatomic' était NOT fourni).

Je tiens également à noter que, depuis votre propriété fait référence à un NSString, qui met en œuvre le protocole NSCopying, vous devriez vraiment être en utilisant une copie plutôt que de retenir, à savoir:

@property (nonatomic, copy) NSString * name; 

Cela provoquera le setter synthétisé à utiliser -copy au lieu de -retain, ce qui est plus sûr lorsque vous passez réellement un objet NSMutableString. Une chaîne immuable ne sera finalement conservée que par l'appel -copy, alors qu'une chaîne mutable créerait une nouvelle copie immuable. Ne pas le faire signifie que la chaîne elle-même pourrait être changée après avoir été passée dans le setter, en changeant la valeur sans la connaissance de votre objet.

+0

Même si vous voulez pouvoir modifier un NSMutableString, vous devez remplacer le setter synthétisé par un autre qui effectue une mutableCopy sur la nouvelle valeur. De cette façon, l'original est sûr, et vous pouvez changer votre copie de la chaîne si vous en avez besoin. – Abizern

+0

Oui, et vous définissez également votre propriété en tant que NSMutableString.A noter également: vous ne pouvez pas vérifier si un NSString est vraiment un NSMutableString en utilisant [str isKindOfClass: [NSMutableString class]], car NSString est un 'cluster de classe', ce qui signifie que vous obtenez réellement une instance d'une sous-classe NSString *, qui est également une sous-classe NSMutableString . Votre meilleur pari est d'utiliser -mutableCopy, qui conservera si le récepteur est déjà mutable. –

3

Si vous avez synthétisé les accesseurs pour votre propriété (avec la directive @synthesize), ils prendront soin de libérer l'ivar qui sauvegarde la propriété lorsque la propriété est réaffectée. La seule fois où vous pourriez vouloir libérer explicitement l'ivar est quand votre objet est libéré. Ainsi, votre méthode dealloc pourrait ressembler à ceci:

- (void)dealloc { 
    [name release]; 
    // other cleanup here 
    [super dealloc]; 
} 
+0

Fondamentalement, les propriétés sont simplement des raccourcis pour appeler des getters et des setters. Quoi qu'il arrive dans votre setter se produira lorsque vous définissez la propriété. Dans le setter synthétisé pour conserver et copier les propriétés, il libère l'ancien objet et conserve (ou copie) le nouveau. – Chuck

+0

@chuck Oui, je sais. C'est pourquoi j'ai spécifié que la propriété est gérée tant qu'elle est synthétisée. –

Questions connexes