2009-08-21 7 views
8

Me preguntaba dónde es el mejor lugar para inicializar miembros de la clase singleton.Cocoa - Objeto Singleton: ¿Dónde inicializar las variables miembro?

Estoy usando la implementación de singleton de la guía fundamental de Apple. ¿Podría por favor precisar en qué línea se encuentran los inits? El código es el siguiente:

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

Es posible que desee leer http://boredzo.org/blog/archives/2009-06-17/doing-it-wrong. ¿Realmente quieres un singleton que anule el lanzamiento? Eso solo enmascara errores. –

+0

Y antes de recordar a Jon Hess que está siguiendo los documentos de Apple: escribí esa publicación específicamente en respuesta a los documentos de Apple. –

+0

También vale la pena señalar que las clases no tienen "miembros" de ningún tipo. Lo más cerca que puede obtener es una variable estática en el archivo de implementación de la clase. Y los miembros de la clase no son lo que quieres inicializar de todos modos. Lo que quiso decir es las variables * instance * de la instancia singleton *. –

Respuesta

18

Es como con las clases habituales - añadir este por encima del bloque:

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

    return self; 
} 

Se va a llamar cuando se accede a Singleton primera vez.

+0

si creo ese método init, entonces sería accesible directamente sin pasar por el sharedManager, ¿verdad? Ahora, si lo hago de forma privada, eso no reemplazará el método init(), ¿verdad? –

+0

Sí, se puede acceder directamente, pero no creo que deba ser así, Singleton se asegurará de que se llame la primera vez que se necesite. Simplemente llama al mensaje [[MySingletonClass sharedClass]] como de costumbre ... – Rudi

+0

+1, como lo señala Jon Hess, por lo general no debes sobrecargar todos estos métodos a menos que realmente tengas que asegurarte de que hay una y solo una instancia de este objeto . Eso es bastante raro en la práctica. En general, solo quiere facilitar el acceso a uno compartido, y para eso solo necesita implementar un método + sharedInstance (o + sharedManager, o lo que sea) que devuelva una instancia estática, y no se preocupe si un llamador solicita explícitamente un único ejemplo. –

1

Puede inicializarlos en el método init, como cualquier otra clase.

Sin embargo, tenga en cuenta que si su singleton contiene un estado miembro, es posible que ya no sea seguro para la rosca. Como se puede acceder a un singleton en cualquier lugar de la aplicación en cualquier momento, se puede acceder desde diferentes hilos.

Cuestiones relacionadas