2009-08-21 20 views
8

Mi chiedevo dove sia il posto migliore per inizializzare i membri della classe Singleton.Cocoa - Oggetto Singleton: dove inizializzare le variabili membro?

Sto usando l'implementazione di base guida Apple singleton. Potresti per favore individuare in quale linea si verificano gli inits? Il codice è il seguente:

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

Si potrebbe voler leggere http://boredzo.org/blog/archives/2009-06-17/doing-it-wrong. Vuoi davvero un singleton che sovrascriva il rilascio? Questo maschera solo bug. –

+0

E prima di ricordare a Jon Hess che stai seguendo i documenti Apple: ho scritto quel post in particolare in risposta ai documenti Apple. –

+0

Vale anche la pena notare che le classi non hanno "membri" di alcun tipo. Il più vicino che puoi ottenere è una variabile statica nel file di implementazione della classe. E i membri della classe non sono ciò che vuoi inizializzare comunque. Quello che intendevi dire è le variabili * instance * dell'istanza * singleton *. –

risposta

18

E 'come con le classi di solito - aggiungere questo al di sopra del blocco:

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

    return self; 
} 

Si chiamerà quando Singleton si accede prima volta.

+0

se creo quel metodo init, quindi sarebbe accessibile direttamente senza passare attraverso il sharedManager, giusto? Ora, se lo rendo privato, questo non sostituirà il metodo init(), giusto? –

+0

Sì, è accessibile direttamente, ma non penso che dovrebbe essere - singleton si assicurerà che venga chiamato la prima volta che è necessario. Hai appena chiamato [[MySingletonClass sharedClass] messaggio come al solito ... – Rudi

+0

+1, come notato da Jon Hess in genere non dovresti sovraccaricare tutti questi metodi a meno che tu non debba assolutamente assicurarti che ci sia una sola istanza di questo oggetto . Questo è piuttosto raro in pratica. In generale, vuoi semplicemente rendere più semplice l'accesso a uno condiviso, e per questo devi solo implementare un metodo + sharedInstance (o + sharedManager, o qualsiasi altra cosa) che restituisce un'istanza statica, e non ti preoccupare se un chiamante richiede esplicitamente un unico esempio. –

1

È possibile inizializzarli nel metodo init, come qualsiasi altra classe.

Tuttavia, prestare attenzione al fatto che se il proprio singleton contiene uno stato membro, potrebbe non essere più protetto da thread. Poiché un singleton è accessibile ovunque nell'app in qualsiasi momento, è possibile accedervi da diversi thread.

Problemi correlati