2009-04-26 5 views
1

Apple fait cela dans une méthode setter pour une instance mainSprocket variable:Pourquoi devrais-je envoyer -autorelease à ma variable d'instance dans ma méthode setter, plutôt que -release?

– (void)setMainSprocket:(Sprocket *)newSprocket { 
    [mainSprocket autorelease]; 
    mainSprocket = [newSprocket retain]; 
    return; 
} 

Pourquoi ils n'envoyer -autorelease et non -RELEASE? Une libération aurait-elle un mauvais effet ici? En fait, cela ne devrait pas (pour autant que je sache), car la -release dit simplement que l'objet courant détenu par la variable d'instance mainSprocket n'est plus utilisé par cette variable d'instance. Dans le cas où quelqu'un d'autre est toujours intéressé par exactement cet objet, cette méthode pourrait le retenir, non? Donc, la libération devrait être bien, je pense?

Répondre

3

Ils font autorelease ici dans le cas où newSprocket et mainSprocket se trouvent être le même objet. Un appel à release peut involontairement libérer l'objet avant qu'il puisse être conservé sur la ligne suivante, tandis que le autorelease ne sera pas traité jusqu'à ce que le pool autorelease soit drainé à la fin de la boucle d'événements.

Tenir compte de ce scénario:

Sprocket *mySprocket = [Sprocket spacelySprocket]; 
[sprocketManager setMainSprocket:mySprocket]; 

Sprocket *anotherPointerToMySprocket = mySprocket; 
[sprocketManager setMainSprocket:anotherPointerToMySprocket]; 

La dernière ligne causerait un problème si mainSprocket n'a pas été autoreleased. Une autre convention que vous pourriez voir parfois pour le code setter qui fait la même chose est:

– (void)setMainSprocket:(Sprocket *)newSprocket { 
    if (newSprocket != mainSprocket) { 
     [mainSprocket release]; 
     mainSprocket = [newSprocket retain]; 
    } 
} 

Je vais laisser aux autres de commenter ce qui est plus approprié ou esthétique :-)

+0

Merci. Mais si ce n'est pas le même objet, et j'appelle cette méthode plusieurs fois, est-ce que je n'aurais pas de problèmes avec le pool autorelease? Parce que la piscine peut être vidangée uniquement dans la fonction principale de l'application? – Thanks

+0

Vous pouvez vider vous-même le pool d'autorelease si vous travaillez dans une fonction où de nombreux objets sont créés. –

+0

Si le flux de programme que vous êtes en train de construire appelle la fonction plusieurs fois, vous pouvez utiliser l'une des autres stratégies d'Apple pour les setters, plutôt que de les verbatim à partir de leur exemple simple que vous citez. Soit mettre en place une réserve automatique d'autorelease et la vidanger vous-même (ou vider le pool autorelease principal manuellement, comme le suggère gs), soit ne pas utiliser autorelease ... utiliser soit la vérification d'identité if soit la retenue de sécurité suggérée par gs. L'approche que vous prenez dépend entièrement de vos besoins. –

4

Si mainSprocket et newSprocket étaient le même objet, il pourrait être libéré si vous utilisez un release simple.

Si vous ne souhaitez pas utiliser autorelease, utilisez ceci:

– (void)setMainSprocket:(Sprocket *)newSprocket { 
    // if newSprocket and mainSprocket were the same object, 
    // it would first be retained and then released 
    // and therefore not deleted. 
    [newSprocket retain]; 
    [mainSprocket release]; 
    mainSprocket = newSprocket; 
    // you don't need return in a void-method 
    // return; 
} 

Pourquoi ne vous utilisez des propriétés? Ils sont la manière Objective-C 2.0 de le faire.

SomeObject.h

@interface SomeObject : NSObject { 
    Sprocket *mainSprocket; 
} 

@property(retain) Sprocket *mainSprocket; 

@end 

SomeObject.m

@implementation SomeObject 

@synthesize mainSprocket; 

@end 
+0

Merci. J'utilise des propriétés, mais je veux être derrière la scène ce qui se passe :) – Thanks

Questions connexes