2009-03-24 15 views
4

Quelle est la meilleure pratique pour conserver et libérer des objets transmis aux méthodes de classe?Comportement de conservation des objets des méthodes de classe Objective-C

Par exemple, si vous avez une "variable de classe" déclarée comme ceci:

static NSString *_myString = nil 

... est la bonne chose à faire:

+ (void)myClassMethod:(NSString *)param { 
    _myString = param; 
} 

... qui a inconvénient que l'appelant doit maintenir un nombre de retenue non nul sur param afin qu'il ne soit pas libéré prématurément. En variante, on pourrait le faire:

+ (void)myClassMethod:(NSString *)param { 
    [_myString autorelease]; 
    _myString = [param retain]; 
} 

... qui présente l'inconvénient que, sans une classe de niveau dealloc appel correspondant il fuite de mémoire. Ou devrait-on éviter complètement ce genre de chicanerie variable de classe, peut-être avec une classe singleton qui gère la vie de ces sortes d'objets d'une manière plus conventionnelle?

Voici Apple's docs on creating a singleton instance.

Le code avec lequel je travaille est le projet de ressource objectif très lisse (mais toujours nouveau) (http://www.iphoneonrails.com/).

+0

Vous posez la mauvaise question. Au lieu de demander comment faire des variables globales, vous devriez demander de l'aide pour vous débarrasser de vos globales. Et oui, même si vous cachez ceci derrière une méthode de classe (ou comme Singleton), c'est toujours une variable globale. – Sven

Répondre

3

Retenir et relâcher, absolument. Ce n'est pas une fuite parce que la seule fois où le dealloc d'une classe serait appelée est quand le programme se termine - à ce moment la mémoire sera libérée de toute façon. Le faire de la première façon serait plus compliqué et va à l'encontre des directives de gestion de la mémoire de Cocoa. Comme s'il s'agissait d'une méthode de classe ou d'un singleton: Les classes elles-mêmes ne devraient généralement pas avoir beaucoup de fonctionnalités indépendantes. Ils n'étaient pas conçus de cette façon en Objective-C, comme vous pouvez le voir par l'absence de variables de classe. Les méthodes de classe doivent généralement traiter de la création et de la gestion des instances, et parfois stocker des propriétés partagées ou des valeurs par défaut pour toutes les instances. La fonctionnalité réelle d'une classe devrait aller dans les instances. C'est la convention en Objective-C.

(Bien sûr, il n'y a pas de Dieu Objective-C et vous êtes libre d'ignorer les conventions, mais c'est la sagesse générale.)

+0

Les classes n'ont pas de méthode dealloc, seules les instances le font. – dreamlax

+0

Oui, il n'y a pas de dealloc pour une classe - mais ça n'a pas d'importance.La mémoire légitimement détenue par un global à la fin du programme n'est normalement pas considérée comme une fuite (tous les singletons fonctionnent comme ça). Utilisez certainement une retenue. –

+0

Je sais que les classes n'ont pas de méthodes dealloc. C'est ce que je voulais dire: même si les cours avaient de telles méthodes, ils ne seraient jamais appelés. – Chuck

3

En outre, dans le cas de NSString ou d'une classe qui a des variantes mutables (comme NSArray ou NSDictionary), je recommande fortement de copier le paramètre au lieu de le conserver. Si la chaîne que l'appelant vous a transmise était NSMutableString, sa valeur pourrait changer plus tard, et elle changera également dans votre classe. Ceci est probablement pas ce que vous voulez, je vous conseille de le faire:

+ (void)myClassMethod:(NSString *)param { 
    [_myString release]; 
    _myString = [param copy]; 
} 

La méthode copy fait une copie et définit la vous êtes tous ensemble comte Retain 1, donc autant que conservant la variable concerné. Et, en bonus, si l'appelant vous passe un NSString, cette classe est assez intelligente pour savoir que sa valeur ne peut pas changer, donc elle se retient simplement pour éviter de faire une copie de l'objet. Comment est-ce intelligent?