2010-02-05 6 views
3

J'utilise la classe MyGizmoClass Singleton d'Apple pour les «variables de session» à l'échelle du programme et j'adore! Cependant, lorsque je lance "Build and Analyze", cela donne des résultats bizarres. Peut-être que mon utilisation est fausse (cela fonctionne, mais cela peut fonctionner à cause d'un effet secondaire flakey). Voici un exemple.Singletons dans Objective-C pour stocker et accéder aux variables à l'échelle du programme. Quelques questions

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 

    int ct = 0; 
    MyGizmoClass *myGizmoClass= [MyGizmoClass sharedManager]; 
    ct = [[myGizmoClass searchResultsForResortLocation] count]; 
    [myGizmoClass release]; 
    NSLog(@"ct: %d",ct); 
    return ct; 
} 

ou

- (void)viewWillAppear:(BOOL)animated { 


    // Uncomment the following line to display an Edit button in the navigation bar for this view controller. 
    //self.navigationItem.rightBarButtonItem = self.editButtonItem; 

    NSMutableString *which_resort = [[NSMutableString alloc] init]; 
    NSMutableString *category_code = [[NSMutableString alloc] init]; 
    MyGizmoClass *myGizmoClass= [MyGizmoClass sharedManager]; 

    ... 

    which_resort = [self which_resort_location_are_we_in]; 

    ... 
    [myGizmoClass setWhich_resort:which_resort]; 

    int useDebugMode = [myGizmoClass useDebugMode]; 

    ... 


    [myGizmoClass release]; 

    [which_resort release]; 
    [category_code release]; 

    [super viewWillAppear:animated]; 

} 

Encore une fois, cet usage peut être loin, mais je pensais que chaque méthode je une valeur de singleton je devais faire:

MyGizmoClass *myGizmoClass= [MyGizmoClass sharedManager]; 

et

[myGizmoClass release]; 

MAIS je reçois ces erreurs lors Analyser:

/Users/jgobble/Documents/ProgramName/Classes/ResortsListViewController.m:495:2 décrément incorrect du comte référence d'un objet n'appartient pas à ce point par l'appelant /Users/jgobble/Documents/ProgramName/Classes/ResortsListViewController.m:493:30 méthode retourne un objet Objective-C avec 0 conserver comptage (non propriétaire référence) /Users/jgobble/Documents/ProgramName/Classes/ResortsListViewController.m: 495: 2 Décrément incorrect de la référence compte d'un objet ne possédait pas au ce point par l'appelant

Maintenant, s'il vous plaît prendre en compte: J'appelle ceci:

MyGizmoClass *myGizmoClass= [MyGizmoClass sharedManager]; 

au début de chaque méthode ont besoin d'une « variable de session », puis appeler :

[myGizmoClass release]; 

à la fin de ce procédé antérieur pour renvoyer un résultat (si je retourne un résultat à partir de cette fonction.

Est-ce que ce n'est pas comme ça que je devrais le faire?

Ceci est la seule chose que l'analyseur (Dieu merci) signale un problème avec le programme. Je ne sais pas si je devrais l'ignorer. Je ne sais pas si je fais les appels au bon endroit.

Voici une autre question qui m'inquiète: Est-ce que cela fonctionne ou est-ce que les appels suivants à * myGizmoClass gâchent quelque chose?

-(void) function_a { 
    MyGizmoClass *myGizmoClass= [MyGizmoClass sharedManager]; 

    [myGizmoClass setC:1]; 

    int result_b = [self function_b]; 

    printf("Addition result is: %d", result_b); 

    [myGizmoClass release] 
} 

-(int) function_b { 
    MyGizmoClass *myGizmoClass= [MyGizmoClass sharedManager]; 

    int b = 0; 

    b = b + [myGizmoClass c]; 

    [myGizmoClass release] 

    return b; 
} 

(je ne l'ai pas testé le code ci-dessus)

En d'autres termes, il y a un problème avec l'appel MyGizmoClass * myGizmoClass = [MyGizmoClass sharedManager]; de function_b lorsque vous n'avez pas publié MyGizmoClass * myGizmoClass = [MyGizmoClass sharedManager]; de function_a?

+1

+1 Une bonne question qui a été très bien présentée. – TechZen

Répondre

5

Le problème est la façon dont vous utilisez un singleton. L'idée générale est que vous ne devez pas retain ou release tous les objets singleton, car il n'y a qu'une seule instance qui se bloque, et l'implémentation Apple de singletons sont codés de telle sorte que vous ne peut pas. Cela provoque certains problèmes que Peter Hosey blogged about avec une meilleure mise en œuvre d'un singleton Cocoa.

Les avertissements que les journaux Analyzer indiquent simplement que vous ne devriez pas conserver ou libérer l'objet singleton; en raison du fait que vous appelez [MyGizmoClass sharedManager] vous ne devriez pas être libérant de toute façon (suite à la Cocoa memory management guidelines).

+0

donc, avec l'exemple de la variable: 'c' type int (dans MyGizmoClass.h) je l'ai défini comme: @property int c; mais s'il s'agissait d'une chaîne NSS: @property (nonatomic, retain) NSString * c; est la façon dont je le ferais. Voulez-vous dire que NSString devrait ressembler à: @property (nonatomic) NSString * c; et je ne devrais jamais appeler [release myGizmoClass]? Je peux comprendre cela ... mais quand et où dois-je appeler: si je le veux disponible pour toute la classe que je suis? Est-ce que je l'appelle encore au début de chaque fonction/méthode? – Jann

+1

La notion de Peters selon laquelle les singletons ne devraient pas remplacer la conservation/libération est, à mon avis, totalement erronée. Les objets devraient être robustes face à l'abus de programmeur - si vous devez le faire, lancez une exception dans la version en mode débogage pour corriger le mauvais comportement de codage. Mais vous voulez éviter la possibilité d'avoir un voyous conserver décrocher l'ensemble de l'application, ce qui ne protège pas singleton laisse grande ouverte. La défense ET la stabilité en profondeur sont essentielles pour le développement d'applications. –

+0

@Jann: L'idée derrière singletons est qu'une seule instance est créée - ceci est fait dans la méthode '-sharedManager' où une instance statique de' MyGizmoClass' est créée (une seule fois) et retournée. En tant qu'optimisation, l'instance est susceptible d'être créée lors du premier appel à '-sharedManager'. De ce fait, vous pouvez accéder au gestionnaire partagé quand vous en avez besoin et vous n'avez pas besoin de le stocker dans un ivar ou quoi que ce soit, alors oui. –

0

Vous ne devriez pas publier myGizmoClass. Lorsque [MyGizmoClass sharedManager] est appelé, l'objet renvoyé n'est pas conservé.Puisqu'il s'agit d'un objet partagé, son seul propriétaire est sa classe. L'autre objet est responsable de le libérer, à moins qu'il ne le conserve d'abord.

Jetez un oeil à ce short guide d'Apple sur l'utilisation d'objets singleton dans votre code Objective-C.

+0

@Marc Désolé, j'ai oublié de vous dire que MyGizmoClass Singleton d'Apple annule silencieusement la conservation/libération. Cela ferait une différence quant à savoir si ma "release" a fait quelque chose ou non ... si l'on l'utilise encore en se référant à un singleton correctement implémenté, cela est incorrect selon les déclarations ci-dessus. Thx – Jann