2009-06-18 7 views
1

Je suis en train de créer une application iPhone dans laquelle je détache des threads pour effectuer un travail de longue durée en arrière-plan afin de ne pas accrocher l'interface utilisateur. Je comprends que les threads ont besoin d'instances NSAutoreleasePool pour la gestion de la mémoire. Ce dont je ne suis pas sûr, c'est si la méthode threadée appelle une autre méthode - cette méthode nécessite-t-elle aussi un NSAutoreleasePool?NSAutoreleasePool portant sur les méthodes?

code Exemple:

- (void)primaryMethod { 
    [self performSelectorInBackground:@selector(threadedMethod) withObject:nil]; 
} 

- (void)threadedMethod { 
    NSAutoreleasePool *aPool = [[NSAutoreleasePool alloc] init]; 

    // Some code here 

    [self anotherMethod]; 

    // Maybe more code here 

    [aPool drain]; 
} 

- (void)anotherMethod { 
    // More code here 
}

La raison pour laquelle je demande est que je reçois des erreurs que les objets sont autoreleased sans piscine en place, et sont « juste fuite. »

J'ai vu d'autres questions pour lesquelles les gens ne disposaient pas des piscines autorelease en place du tout, et je comprends pourquoi une piscine autorelease est nécessaire. Je suis particulièrement intéressé à savoir si un pool autorelease créé dans (dans cet exemple) threadedMethod s'applique aux objets créés dans anotherMethod.

+0

La réponse courte est oui. Voir ma réponse. – SwiftArchitect

Répondre

7

Pour répondre à votre question, oui, anotherMethod utilise le NSAutoreleasePool vous avez créé à threadedMethod, et tout ce que vous AutoRelease il sortira quand APool est libéré/égoutté.

Il est donc peu probable que votre erreur provienne directement de ce code (sauf s'il y a plus de choses qui se passent). Mettez un point d'arrêt sur _NSAutoreleaseNoPool (ajoutez-le par son nom dans la fenêtre Points d'arrêt) et exécutez votre code dans le débogueur. Il s'arrête lorsque autorelease est appelée sans pool et que cela devrait résoudre votre problème.

+1

+1 pour le point d'arrêt sur la suggestion _NSAutoreleaseNoPool. Cela a aidé à éliminer les messages d'erreur. – Tim

+0

Qu'en est-il des méthodes class, +,? – Zsolt

+0

Et à propos d'eux? Toute méthode, classe ou autre, appelée à partir de threadedMethod utilisera le NSAutoreleasePool créé dans threadedMethod (ou un autre NSAutoreleasePool créé plus profondément imbriqué). –

-1

La piscine autorelease ne porte jusqu'à anotherMethod. Cependant, lorsque votre fonction filetée se termine, vous devriez appeler [release aPool] au lieu de [aPool drain]. Ils sont à peu près équivalents, mais la version aPool provoque la libération de NSAutoreleasePool en plus de tous les autres objets du pool. Lorsque votre fonction filetée se termine après avoir appelé drain, le pool autorelease a toujours un nombre de retenue de +1! Les chances sont, l'objet «juste fuite» est unPool!

EDIT:

Jim Puls a raison sur la libération et de drain étant équivalent. Les docs d'Apple disent clairement qu'ils sont identiques dans l'environnement non-garbage collecté, et l'évacuation est meilleure dans le cas des déchets collectés. Ma faute pour ne pas lire les docs!

Voici un article qui présente un aperçu général des NSAutoreleasePools - il devrait aider à vous orienter dans la bonne direction. Puisqu'il existe une pile virtuelle de pools de libération automatique, la plus haute sera utilisée partout dans votre application - quel que soit l'endroit où les objets sont auto-libérés.

http://thegothicparty.com/dev/macos/nsautoreleasepool/

+3

C'est, euh, pas vrai: http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSAutoreleasePool_Class/Reference/Reference.html#//apple_ref/doc/uid/20000051-SW1 –

+3

Pour élaborer , les pools d'autorelease ne sont pas comptés eux-mêmes; ils forment une pile où les objets autoreleased vont dans le plus haut pool. -drain, -release, et la fin de chaque itération de la boucle d'exécution vient faire apparaître la pile des pools autorelease. –

+0

Ben: est-ce vrai aussi à travers les méthodes de classe? Dites, si une autre méthode existait dans AnotherClass, et que j'ai instancié anotherClass dans threadedMethod - le code exécuté dans [anotherClass anotherMethod] est-il toujours auto-libéré? – Tim

0

Dans votre exemple, oui, NSAutoreleasePool transporte d'autres méthodes car l'appel de [self anotherMethod] est imbriqué à l'intérieur - (void)threadedMethod.

  • Q: NSAutoreleasePool portant des méthodes croisées?
  • A: Cela dépend:
    1. À travers les invocations imbriquées, oui.
    2. Pour les invocations de frères et soeurs, no.

Et peu importe ce que, l'NSAutoreleasePool instance elle-même est hors de portée lorsque la portée des parents disparaît. -dans votre exemple, à la fin de -(void)threadedMethod { }.

L'article mentionné précédemment (http://thegothicparty.com/dev/macos/nsautoreleasepool/) est assez clair à ce sujet.

Questions connexes