2010-08-31 4 views
6

Je viens de télécharger le Facebook iOS SDK et je remarquai que, dans l'exemple de code fourni avec le SDK chaque fois qu'il crée une instance de la classe Facebook il le fait comme ceci:Effet de 'myObj = [[[[MyClass alloc] init] autorelease] conserve];'?

_facebook = [[[[Facebook alloc] init] autorelease] retain]; 

_facebook est une variable membre de l'objet appelant (c'est-à-dire pas une variable locale). Est-ce que quelqu'un peut expliquer exactement quel est le point d'auto-libération, puis de le conserver?

+3

Um, que diable ??? –

+2

Hmm, je pense que je ferais mieux de désinstaller l'application Facebook. Ils ne comprennent clairement pas ce qu'ils font. – JeremyP

Répondre

13

En fait, il ne fait rien d'autre que de consommer des cycles et de la mémoire.

Ou, plus précisément, dans une application correctement écrite, il ne fait rien. Dans une application mal écrite, il peut masquer un bogue en allongeant la durée de vie de l'objet _facebook. Cependant, ce n'est pas une vraie solution.

J'ai trouvé une ligne de code similaire dans http://github.com/facebook/facebook-ios-sdk/blob/master/sample/DemoApp/Classes/DemoAppViewController.m Si c'est de cela que vous parlez alors, oui, c'est un non-sens.

+8

La théorie alternative est que c'est un symptôme de mémorisation sans compréhension. "Pour créer un objet, je dois écrire [[[ClassName alloc] init] autorelease]; s'y accrocher; Je dois le garder. "Seul l'auteur de la déclaration sait à coup sûr. –

+0

Exécution blâmer sur ce dossier l'attribue à un dev, peut-être quelqu'un devrait envoyer un email demandant des précisions sur Github;) http://github.com/facebook/facebook-ios-sdk/blame/master/sample/DemoApp/Classes /DemoAppViewController.m – Shazron

+0

Ouais, c'est ce que je pensais ... mais étant dans le SDK "officiel" de Facebook, je pensais que le développeur d'origine savait peut-être quelque chose que je n'avais pas, alors j'ai pensé que je demanderais. Merci pour votre contribution. – filipe

1

Bien qu'il soit possible que le code que vous avez trouvé était simplement bâclé, ce modèle a une signification.

"alloc, autorelease, conserver" implique que l'objet est référencé dans deux endroits:

  • En tant que valeur de retour sur la pile d'appel (style autorelease)
  • par le SDK FB lui-même (le ' retenir ')

Cela est important si les deux références peuvent être libérées indépendamment. Par exemple, si le SDK peut libérer sa référence AVANT que la pile d'appel soit terminée et vider le pool de libération automatique. Ok, c'est assez nuancé; Qu'est ce que je veux dire?

Tenir compte de ces cas:

A) le code réel

_facebook = [[[[Facebook alloc] init] autorelease] retain]; 

_facebook a maintenant conserver le nombre de 2, et attend 2 appels à la 'libération': 1 de celui qui a appelé " retenez ", et 1 à un moment donné dans le futur lorsque le NSAutoreleasePool se vide.

B) simple "alternative" proposée (non équivalent)

_facebook = [[Facebook alloc] init]; 

_facebook a un retain nombre de 1 et sera détruit lors de 'libération' est appelé (potentiellement un gros problème si le pool d'autorelease n'a pas encore été drainé et la pile d'appels utilise toujours l'objet)

Pourquoi est-ce important? Imaginez un code comme celui-ci:

@implementation (Thinger) 
+(id) make_new_thing 
{ 
    return my_copy_of_thing = [[[[Thing alloc] init] autorelease] retain]; 
} 
+(id) forget_about_thing 
{ 
    if (my_copy_of_thing != nil) { 
     [my_copy_of_thing release]; 
     my_copy_of_thing = nil; 
    } 
} 
@end 


void foo() { 
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; 
    id thing = [Thinger make_new_thing]; 
    [Thinger forget_about_thing]; 
    ... 
    [thing useThing]; // implementation B would break here ! 
    [pool drain]; 
} 
+0

Juste pour être clair, il est certainement * pas * convention d'écrire jamais [[[[MyClass alloc] init] autorelease] conserver] '. Plutôt, la méthode '+ make_new_thing 'mentionnée ci-dessus renvoie une instance complètement nouvelle d'un objet autoreleased (c'est-à-dire' return [[[MyClass alloc] init] autorelease] ') et ne conserve pas la référence à l'ancien. Ce serait une très mauvaise conception d'avoir une méthode "créer" qui pourrait potentiellement libérer des objets précédemment créés avec elle à chaque appel. – Sean

+0

Oui, l'exemple que j'ai donné était plutôt artificiel. C'est "correct" cependant. Ma méthode make_new_thing appelle "release" parce qu'elle abandonne sa référence "my_copy_of_thing". Il ne fait que "désallouer les objets créés précédemment" s'il n'y a pas d'autres références à ces objets. –

+0

Désolé, mais non, ce n'est pas correct. Le fait que l'on devrait écrire '... alloc] init] autorelease] conserve]' est un signe que le design * lui-même * est incorrect. Il existe de meilleures façons de concevoir ce type de fonctionnalité qui permettrait d'éviter à la fois la gestion de la mémoire folle et les effets secondaires bizarres de la méthode create. – Sean

Questions connexes