EDITAR
Estoy incluyendo esta en la parte superior, a continuación se puede ver mis preguntas originales históricos y aplicación.Sin embargo creo que he encontrado la mejor manera de proporcionar un método sharedInstance con ninguna sobrecarga de bloqueo, me gustaría escuchar las posibles preocupaciones acerca de esto:
// Volatile to make sure we are not foiled by CPU caches
static volatile ALBackendRequestManager *sharedInstance;
// There's no need to call this directly, as method swizzling in sharedInstance
// means this will get called after the singleton is initialized.
+ (MySingleton *)simpleSharedInstance
{
return (MySingleton *)sharedInstance;
}
+ (MySingleton*)sharedInstance
{
@synchronized(self)
{
if (sharedInstance == nil)
{
sharedInstance = [[MySingleton alloc] init];
// Replace expensive thread-safe method
// with the simpler one that just returns the allocated instance.
SEL orig = @selector(sharedInstance);
SEL new = @selector(simpleSharedInstance);
Method origMethod = class_getClassMethod(self, orig);
Method newMethod = class_getClassMethod(self, new);
method_exchangeImplementations(origMethod, newMethod);
}
}
return (MySingleton *)sharedInstance;
}
Y la discusión histórica en torno a inicializar:
I ver ahora el código original era bastante parecido al mío (abajo), excepto por tener el cheque de la instancia fuera del candado.
Aunque el nuevo método de inicialización + (vacío) es interesante, no estoy seguro de que me guste más. Parece que ahora para obtener una instancia singleton, ahora siempre debe llamar:
MySingleton instance = [[MySingleton alloc] init];
¿No es eso correcto? Eso se siente extraño, ¿y es más eficiente si la llamada para inicializar ya está bloqueada para usted? El método de doble bloqueo parece funcionar bien para este caso de uso, al tiempo que también evita el bloqueo (al costo potencial de una doble asignación, creo que debido a que más de un hilo podría caer a través del if).
La otra cosa que parece extraña si, si el método de inicialización fuera realmente preferido, ¿por qué no lo vemos en otro lugar? Objective-C ha existido por MUCHO tiempo y desconfío de los mecanismos fundamentales que difieren de casi todos los ejemplos publicados.
Mi código Actualmente uso (que refleja que he visto en otros lugares, incluyendo this respuesta):
+ (MySingleton *)sharedInstance
{
@synchronized(self)
{
if (sharedInstance == nil)
sharedInstance = [[MySingleton alloc] init];
}
return sharedInstance;
}
+ (id)allocWithZone:(NSZone *)zone
{
@synchronized(self)
{
if (sharedInstance == nil)
{
sharedInstance = [super allocWithZone:zone];
return sharedInstance; // assignment and return on first allocation
}
}
return nil; // on subsequent allocation attempts return nil
}
No edite su pregunta de forma que invalide o deje de ser relevante. – dreamlax
¿Por qué otro subproceso singleton de Objective-C? Ver http://stackoverflow.com/questions/145154 para ejemplos. – zoul
¿No usaría Gallagher's .. http://projectswithlove.com/projects/SynthesizeSingleton.h.zip desde http://cocoawithlove.com/2008/11/singletons-appdelegates-and-top-level.html. ..? – Fattie