Objet d'allouer et d'init en Objective-C
Quelle est la différence entre les 2 façons de répartir et d'initialisation d'un objet?
AController *tempAController = [[AController alloc] init];
self.aController = tempAController;
[tempAController release];
et
self.aController= [[AController alloc] init];
La plupart des apple exemple d'utiliser la première méthode. Pourquoi voudriez vous allouer, init et de l'objet, puis relâchez immédiatement?
Vous devez vous connecter pour publier un commentaire.
Chaque objet dispose d'un compteur de référence. Quand il passe à 0, l'objet est libéré.
En supposant que le bien a été déclaré comme
@property (retain)
:Votre premier exemple, ligne par ligne:
alloc
, il a un nombre de références 1.self
'ssetAController:
méthode, qui envoie unretain
message (parce que la méthode ne sait pas où l'objet est à venir à partir de), incrémenter son compteur de référence à 2.release
, décrémenter le compteur de référence à 1.Votre deuxième exemple fait les étapes 1 et 2 mais pas 3, donc à la fin de l'objet de comptage de référence est de 2.
La règle est que si vous créez un objet, vous êtes responsable de la relâcher lorsque vous avez terminé avec elle. Dans votre exemple, le code est fait avec tempAController après il définit la propriété. C'est la méthode de définition de la responsabilité de faire appel
retain
si elle a besoin de cet objet pour rester dans les parages.Il est important de se rappeler que
self.property = foo;
en Objective-C est vraiment juste un raccourci pour[self setProperty:foo];
et que lesetProperty:
méthode sera retenue ou de la copie d'objets que nécessaire.Si le bien a été déclaré
@property (copy)
, l'objet aurait été copié à la place de retenue. Dans le premier exemple, l'objet d'origine serait libéré immédiatement; dans le deuxième exemple, l'objet original de comptage de référence serait de 1, même si elle devrait être 0. Si vous le souhaitez écrire votre code de la même façon.Si le bien a été déclaré
@property (assign)
, puisself
n'est pas revendiquant la propriété de l'objet, et quelqu'un d'autre doit le conserver. Dans ce cas, le premier exemple serait incorrect. Ces sortes de propriétés sont rares, habituellement utilisée uniquement pour objet de délégués.Comme d'autres l'ont noté, les deux extraits de code vous montrer ne sont pas équivalents (pour la gestion de la mémoire raisons).
Pourquoi le premier est choisi sur celle-ci:
La formulation correcte de ce dernier serait
Par rapport à l'ancien, ce qui ajoute une charge supplémentaire grâce à l'utilisation de l'autorelease pool, et dans certaines circonstances conduira à la durée de vie de l'objet inutilement prolongée (jusqu'à ce que l'autorelease pool est sorti), qui permettra d'augmenter la mémoire de votre application empreinte.
L'autre "possible" mise en œuvre (selon l'endroit où l'exemple est tiré d') est tout simplement:
Toutefois, la définition d'une variable d'instance directement est fortement déconseillé de n'importe où ailleurs que dans un ou init méthode dealloc. D'ailleurs vous devriez toujours utiliser des méthodes accesseurs.
Cela nous amène alors à la mise en œuvre illustré dans l'exemple de code:
Ce suit les meilleures pratiques depuis:
Note également que votre désir de réduire le code pour une ligne qui est pourquoi beaucoup de gens utilisent Autorelease:
Si, en théorie, sur l'iPhone autorelease est en quelque sorte plus cher (jamais entendu parler d'une explication claire pourquoi) et donc vous pouvez libérer explicitement à droite après l'affectation de l'objet par ailleurs.
Si vous êtes en utilisant Xcode, il peut vous aider à détecter ce genre de code avec l'analyseur statique.
Il suffit de frapper Build >> Construire et Analyser
Cela va vous montrer très utile message à ces morceaux de code.
Une autre chose à noter est que votre exemple, dépend de la @définition de propriété de aController aussi.
Si elle a été définie comme
@property (readwrite, retain) id aController;
alors votre exemple, alors que si elle est définie comme@property (readwrite, assign) id aController;
puis l'appel supplémentaire à la libération serait la cause de votre objet à être libéré.Vous pouvez également faire de
avec une retenue à la propriété, et il devrait fonctionner de la même manière, mais de son mieux pour utiliser l'autre sens (pour conserver les propriétés) parce qu'il est moins à confusion, que le code fait ressembler à vous attribuer aController et puis il est supprimé de la mémoire, alors qu'en réalité, ce n'est pas parce que setAController le retient.