2009-08-21 7 views
8

Je me demandais où est le meilleur endroit pour initialiser les membres de la classe singleton. J'utilise Apple mise en œuvre singleton guide fondamental. Pourriez-vous s'il vous plaît préciser à quelle ligne les inits se produisent? Le code est le suivant:Cocoa - Objet Singleton: Où initialiser les variables membres?

static MyGizmoClass *sharedGizmoManager = nil; 

+ (MyGizmoClass*)sharedManager 
{ 
    @synchronized(self) { 
     if (sharedGizmoManager == nil) { 
      [[self alloc] init]; // assignment not done here 
     } 
    } 
    return sharedGizmoManager; 
} 

+ (id)allocWithZone:(NSZone *)zone 
{ 
    @synchronized(self) { 
     if (sharedGizmoManager == nil) { 
      sharedGizmoManager = [super allocWithZone:zone]; 
      return sharedGizmoManager; // assignment and return on first allocation 
     } 
    } 
    return nil; //on subsequent allocation attempts return nil 
} 

- (id)copyWithZone:(NSZone *)zone 
{ 
    return self; 
} 

- (id)retain 
{ 
    return self; 
} 

- (unsigned)retainCount 
{ 
    return UINT_MAX; //denotes an object that cannot be released 
} 

- (void)release 
{ 
    //do nothing 
} 

- (id)autorelease 
{ 
    return self; 
} 
+2

Vous voudrez peut-être lire http://boredzo.org/blog/archives/2009-06-17/doing-it-wrong. Voulez-vous vraiment un singleton qui annule la libération? Cela ne fait que masquer les bugs. –

+0

Et avant que vous rappelez à Jon Hess que vous suivez les docs d'Apple: j'ai écrit ce post spécifiquement en réponse aux docs d'Apple. –

+0

Il convient également de noter que les classes n'ont aucun "membre" d'aucune sorte. Le plus proche que vous pouvez obtenir est une variable statique dans le fichier d'implémentation de la classe. Et les membres de classe ne sont pas ce que vous voulez initialiser de toute façon. Ce que vous vouliez dire, c'est les variables * instance * de l'instance de singleton *. –

Répondre

18

Il est aussi avec les classes habituelles - ajouter ce bloc au-dessus du:

-(id)init { 
    if (self = [super init]) { 
    // do init here 
    } 

    return self; 
} 

Il sera appelé lorsque singleton est accessible première fois.

+0

si je crée cette méthode init, alors il serait accessible directement sans passer par le sharedManager, n'est-ce pas? Maintenant, si je le rends privé, cela ne surchargera pas la méthode init(), n'est-ce pas? –

+0

Oui, c'est accessible directement, mais je ne pense pas que cela devrait être le cas - singleton s'assurera que c'est appelé la première fois que c'est nécessaire. Vous appelez juste [[MySingletonClass sharedClass] message] comme d'habitude ... – Rudi

+0

+1, comme noté par Jon Hess vous ne devriez généralement pas surcharger toutes ces méthodes sauf si vous devez vraiment absolument vous assurer qu'il y a une et une seule instance de cet objet . C'est plutôt rare en pratique. Généralement, vous voulez simplement faciliter l'accès à un partage, et pour cela vous avez juste besoin d'implémenter une méthode + sharedInstance (ou + sharedManager, ou autre) qui renvoie une instance statique, et ne vous inquiétez pas si un appelant demande explicitement un exemple. –

1

Vous pouvez les initialiser dans la méthode init, comme n'importe quelle autre classe. Cependant, gardez à l'esprit que si votre singleton contient un état membre, il peut ne plus être threadsafe. Depuis un singleton est accessible n'importe où dans l'application à tout moment, il peut être consulté à partir de différents threads.