2011-01-05 19 views
5

Tengo un Singleton configurado de esta manera:Usar Singleton In Interface Builder?

static Universe *instance; 

+ (Universe *)instance { return instance; } 

+ (void)initialize 
{ 
    static BOOL initialized = NO; 
    if(!initialized) 
    { 
     initialized = YES; 
     instance = [[Universe alloc] init]; 
    } 
} 

- (id) init 
{ 
    self = [super init]; 
    if (self != nil) { 
     self.showHistory = YES; 
    } 
    return self; 
} 

pero ahora me doy cuenta de que me gustaría crear una instancia de Interface Builder. Estaba pensando en el corte justo en el método init al igual que

if (instance) 
     return instance; 

se trata de una mala idea? Preferiría que IB recoja la instancia ya creada en el método +initialize.

Respuesta

6

Esto se puede hacer. Hay una sección al respecto en Cocoa Design Patterns por Buck and Yachtman.

En su caso se podría hacer algo a lo largo de las líneas de:

static Universe *instance; 

+ (Universe *)instance { return instance; } 

+ (id)hiddenAlloc 
{ 
    return [super alloc]; 
} 

+ (id)alloc 
{ 
    return [[self instance] retain]; 
} 

+ (void)initialize 
{ 
    static BOOL initialized = NO; 
    if(!initialized) 
    { 
     initialized = YES; 
     instance = [[Universe hiddenAlloc] init]; 
    } 
} 

- (id)init 
{ 
    if(instance==nil) // allow only to be called once 
    { 
    // your normal initialization here 
    } 
    return self; 
} 

La punta código carga entonces escogerá correctamente el producto único a través de su llamada a [[Universe alloc] init], y todavía se puede utilizar instance en su código como antes de.

El libro tiene más detalle y recomienda la implementación de new y allocWithZone (ambos simplemente como return [self alloc];), además de los trozos de informe de errores de atrapar copyWithZone y mutableCopyWithZone intentos para una buena medida.

+1

Esto es lo que hice para implementar un versión de complemento de algún código de cliente de red que originalmente estaba en una aplicación Cocoa. Un compañero de trabajo lo quería en un complemento, así que tomé la ruta singleton, por lo que solo habría una instancia real del cliente de red (internamente). – ExitToShell

+0

@invariant, gran respuesta del tipo que me alegra haber hecho la pregunta y no solo la descarté como tonta. –

+2

'+ alloc' debe devolver' [[self instance] retain] ', porque' alloc' devuelve un objeto propiedad. –

1

Eso va a tener fugas. Puede salirse con la suya si lo cambia a:

if(instance) { 
    [self release]; 
    return instance; 
} 

pero todavía huele un poco a mí. Tengo curiosidad por saber qué uso tienes para los singleton en IB; Sospecho que evitaría esta construcción en mi código.

+0

Hola Seamus, sí, el código no funciona de todos modos debido a "Este codificador requiere que los objetos reemplazados se devuelvan de initWithCoder" ... de todos modos, voy a retirar objetos externos en IB. El punto es que utilizo un singleton central como puente para todas las piezas de la aplicación ... por lo que cada pieza se registra con el singleton. Pero luego pensé, ¿por qué no cablear algunos de ellos? –

+0

http://stackoverflow.com/questions/350861/what-bad-practice-do-you-do-and-why/350900#350900 –

+1

^^ amo ese hilo de confesiones :) –

Cuestiones relacionadas