¿Cómo debería ser mi Objective-C singleton? [cerrado]
Mi método singleton accessor suele ser una variante de:
static MyClass *gInstance = NULL;
+ (MyClass *)instance
{
@synchronized(self)
{
if (gInstance == NULL)
gInstance = [[self alloc] init];
}
return(gInstance);
}
¿Qué podría estar haciendo para mejorar esto?
26 answers
Otra opción es usar el método +(void)initialize
. De la documentación:
El tiempo de ejecución envía
initialize
a cada clase en un programa exactamente una vez justo antes de que la clase, o cualquier clase que herede de ella, reciba su primer mensaje desde dentro del programa. (Por lo tanto, el método nunca puede invocarse si no se utiliza la clase.) El tiempo de ejecución envía el mensajeinitialize
a las clases de una manera segura para subprocesos. Las superclases reciben este mensaje antes que sus subclases.
Para que puedas hacer algo parecido a esto:
static MySingleton *sharedSingleton;
+ (void)initialize
{
static BOOL initialized = NO;
if(!initialized)
{
initialized = YES;
sharedSingleton = [[MySingleton alloc] init];
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-27 02:14:23
@interface MySingleton : NSObject
{
}
+ (MySingleton *)sharedSingleton;
@end
@implementation MySingleton
+ (MySingleton *)sharedSingleton
{
static MySingleton *sharedSingleton;
@synchronized(self)
{
if (!sharedSingleton)
sharedSingleton = [[MySingleton alloc] init];
return sharedSingleton;
}
}
@end
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-28 04:23:16
Según mi otra respuesta a continuación, creo que deberías hacer:
+ (id)sharedFoo
{
static dispatch_once_t once;
static MyFoo *sharedFoo;
dispatch_once(&once, ^ { sharedFoo = [[self alloc] init]; });
return sharedFoo;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-09-19 23:24:34
Desde Kendall publicó un singleton threadsafe que intenta evitar los costos de bloqueo, pensé que lanzaría uno también:
#import <libkern/OSAtomic.h>
static void * volatile sharedInstance = nil;
+ (className *) sharedInstance {
while (!sharedInstance) {
className *temp = [[self alloc] init];
if(!OSAtomicCompareAndSwapPtrBarrier(0x0, temp, &sharedInstance)) {
[temp release];
}
}
return sharedInstance;
}
Bien, permítanme explicar cómo funciona esto:
-
Caso rápido: En ejecución normal
sharedInstance
ya se ha establecido, por lo que el buclewhile
nunca se ejecuta y la función regresa después de simplemente probar la existencia de la variable; Caso lento: Si
sharedInstance
no existe, entonces se asigna una instancia y se copia en ella usando una Comparación E Intercambio ('CAS');Sostuvo caso: Si dos hilos de tanto intento de llamada
sharedInstance
al mismo tiempo YsharedInstance
no existe, al mismo tiempo, entonces ambos inicializar nuevas instancias de singleton y el intento de CAS en la posición. El que gane el CAS devuelve inmediatamente, el que pierda libera la instancia que acaba de asignar y devuelve el (ahora establecido)sharedInstance
. El únicoOSAtomicCompareAndSwapPtrBarrier
actúa como una barrera de escritura para el hilo de ajuste y una barrera de lectura del hilo de prueba.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 10:29:47
static MyClass *sharedInst = nil; + (id)sharedInstance { @synchronize( self ) { if ( sharedInst == nil ) { /* sharedInst set up in init */ [[self alloc] init]; } } return sharedInst; } - (id)init { if ( sharedInst != nil ) { [NSException raise:NSInternalInconsistencyException format:@"[%@ %@] cannot be called; use +[%@ %@] instead"], NSStringFromClass([self class]), NSStringFromSelector(_cmd), NSStringFromClass([self class]), NSStringFromSelector(@selector(sharedInstance)"]; } else if ( self = [super init] ) { sharedInst = self; /* Whatever class specific here */ } return sharedInst; } /* These probably do nothing in a GC app. Keeps singleton as an actual singleton in a non CG app */ - (NSUInteger)retainCount { return NSUIntegerMax; } - (oneway void)release { } - (id)retain { return sharedInst; } - (id)autorelease { return sharedInst; }
Editar: Esta implementación obsoleta con ARC. Por favor, eche un vistazo a ¿Cómo puedo implementar un singleton Objective-C que sea compatible con ARC? para una correcta implementación.
Todas las implementaciones de initialize que he leído en otras respuestas comparten un error común.
+ (void) initialize {
_instance = [[MySingletonClass alloc] init] // <----- Wrong!
}
+ (void) initialize {
if (self == [MySingletonClass class]){ // <----- Correct!
_instance = [[MySingletonClass alloc] init]
}
}
La documentación de Apple recomienda comprobar el tipo de clase en el bloque de inicialización. Porque las subclases llaman a la inicialización por defecto. Existe un caso no obvio donde las subclases pueden crearse indirectamente a través de KVO. Para si agrega la siguiente línea en otra clase:
[[MySingletonClass getInstance] addObserver:self forKeyPath:@"foo" options:0 context:nil]
Objective-C creará implícitamente una subclase de MySingletonClass resultando en una segunda activación de +initialize
.
Puede pensar que debería verificar implícitamente la inicialización duplicada en su bloque de inicio como tal:
- (id) init { <----- Wrong!
if (_instance != nil) {
// Some hack
}
else {
// Do stuff
}
return self;
}
Pero te dispararás en el pie; o peor dar a otro desarrollador la oportunidad de dispararse a sí mismos en el pie.
- (id) init { <----- Correct!
NSAssert(_instance == nil, @"Duplication initialization of singleton");
self = [super init];
if (self){
// Do stuff
}
return self;
}
TL; DR, aquí está mi implementación
@implementation MySingletonClass
static MySingletonClass * _instance;
+ (void) initialize {
if (self == [MySingletonClass class]){
_instance = [[MySingletonClass alloc] init];
}
}
- (id) init {
ZAssert (_instance == nil, @"Duplication initialization of singleton");
self = [super init];
if (self) {
// Initialization
}
return self;
}
+ (id) getInstance {
return _instance;
}
@end
(Reemplace ZAssert con nuestra propia macro de aserción; o simplemente NSAssert.)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:47:35
Una explicación completa del código macro Singleton está en el blog Cocoa With Love
Http://cocoawithlove.com/2008/11/singletons-appdelegates-and-top-level.html .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-01-12 22:45:37
Tengo una variación interesante en sharedInstance que es segura para subprocesos, pero no se bloquea después de la inicialización. Todavía no estoy lo suficientemente seguro de ello para modificar la respuesta principal como se solicitó, pero lo presento para una mayor discusión:
// 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 origSel = @selector(sharedInstance);
SEL newSel = @selector(simpleSharedInstance);
Method origMethod = class_getClassMethod(self, origSel);
Method newMethod = class_getClassMethod(self, newSel);
method_exchangeImplementations(origMethod, newMethod);
}
}
return (MySingleton *)sharedInstance;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-19 08:00:33
Respuesta Corta: Fabuloso.
Respuesta larga: Algo así como....
static SomeSingleton *instance = NULL;
@implementation SomeSingleton
+ (id) instance {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (instance == NULL){
instance = [[super allocWithZone:NULL] init];
}
});
return instance;
}
+ (id) allocWithZone:(NSZone *)paramZone {
return [[self instance] retain];
}
- (id) copyWithZone:(NSZone *)paramZone {
return self;
}
- (id) autorelease {
return self;
}
- (NSUInteger) retainCount {
return NSUIntegerMax;
}
- (id) retain {
return self;
}
@end
Asegúrese de leer el dispatch/una vez.h header para entender lo que está pasando. En este caso, los comentarios de encabezado son más aplicables que los documentos o la página de manual.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-08 03:12:32
He rodado singleton en una clase, por lo que otras clases pueden heredar propiedades singleton.
[3] Singleton.h:static id sharedInstance = nil;
#define DEFINE_SHARED_INSTANCE + (id) sharedInstance { return [self sharedInstance:&sharedInstance]; } \
+ (id) allocWithZone:(NSZone *)zone { return [self allocWithZone:zone forInstance:&sharedInstance]; }
@interface Singleton : NSObject {
}
+ (id) sharedInstance;
+ (id) sharedInstance:(id*)inst;
+ (id) allocWithZone:(NSZone *)zone forInstance:(id*)inst;
@end
[3] Singleton.m:
#import "Singleton.h"
@implementation Singleton
+ (id) sharedInstance {
return [self sharedInstance:&sharedInstance];
}
+ (id) sharedInstance:(id*)inst {
@synchronized(self)
{
if (*inst == nil)
*inst = [[self alloc] init];
}
return *inst;
}
+ (id) allocWithZone:(NSZone *)zone forInstance:(id*)inst {
@synchronized(self) {
if (*inst == nil) {
*inst = [super allocWithZone:zone];
return *inst; // 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;
}
@end
Y aquí hay un ejemplo de alguna clase, que desea convertirse en singleton.
#import "Singleton.h"
@interface SomeClass : Singleton {
}
@end
@implementation SomeClass
DEFINE_SHARED_INSTANCE;
@end
La única limitación sobre la clase Singleton, es que es la subclase NSObject. Pero la mayoría de las veces uso singletons en mi código, de hecho son subclases NSObject, por lo que esta clase realmente facilita mi vida y hace que el código sea más limpio.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-11-30 10:00:44
Esto también funciona en un entorno no recolectado de basura.
@interface MySingleton : NSObject {
}
+(MySingleton *)sharedManager;
@end
@implementation MySingleton
static MySingleton *sharedMySingleton = nil;
+(MySingleton*)sharedManager {
@synchronized(self) {
if (sharedMySingleton == nil) {
[[self alloc] init]; // assignment not done here
}
}
return sharedMySingleton;
}
+(id)allocWithZone:(NSZone *)zone {
@synchronized(self) {
if (sharedMySingleton == nil) {
sharedMySingleton = [super allocWithZone:zone];
return sharedMySingleton; // assignment and return on first allocation
}
}
return nil; //on subsequent allocation attempts return nil
}
-(void)dealloc {
[super dealloc];
}
-(id)copyWithZone:(NSZone *)zone {
return self;
}
-(id)retain {
return self;
}
-(unsigned)retainCount {
return UINT_MAX; //denotes an object that cannot be release
}
-(void)release {
//do nothing
}
-(id)autorelease {
return self;
}
-(id)init {
self = [super init];
sharedMySingleton = self;
//initialize here
return self;
}
@end
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-10 14:48:40
¿No debería ser esto threadsafe y evitar el costoso bloqueo después de la primera llamada?
+ (MySingleton*)sharedInstance
{
if (sharedInstance == nil) {
@synchronized(self) {
if (sharedInstance == nil) {
sharedInstance = [[MySingleton alloc] init];
}
}
}
return (MySingleton *)sharedInstance;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-17 11:13:55
He aquí una macro que he reunido:
Http://github.com/cjhanson/Objective-C-Optimized-Singleton
Se basa en el trabajo aquí de Matt Gallagher Pero cambiando la implementación para usar método swizzling como se describe aquí por Dave MacLachlan de Google.
Agradezco los comentarios / contribuciones.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-09-13 15:25:03
¿Qué tal
static MyClass *gInstance = NULL;
+ (MyClass *)instance
{
if (gInstance == NULL) {
@synchronized(self)
{
if (gInstance == NULL)
gInstance = [[self alloc] init];
}
}
return(gInstance);
}
Para evitar el costo de sincronización después de la inicialización?
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-29 18:32:32
Para una discusión en profundidad del patrón singleton en Objective-C, mira aquí:
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-01-28 02:15:12
KLSingleton es:
- Subclasible (al n-ésimo grado)
- Compatible con ARC
- Seguro con
alloc
yinit
- Cargado perezosamente
- Thread-safe
- Sin bloqueo (usa +inicializar, no @sincronizar)
- Libre de macro
- Libre de Swizzle
- Simple
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-11 20:54:30
No desea sincronizar en sí mismo... ¡Puesto que el objeto del uno mismo no existe todavía! Terminas bloqueando un valor de id temporal. Desea asegurarse de que nadie más pueda ejecutar métodos de clase (sharedInstance, alloc, allocWithZone:, etc.), por lo que necesita sincronizar en el objeto de clase:
@implementation MYSingleton
static MYSingleton * sharedInstance = nil;
+( id )sharedInstance {
@synchronized( [ MYSingleton class ] ) {
if( sharedInstance == nil )
sharedInstance = [ [ MYSingleton alloc ] init ];
}
return sharedInstance;
}
+( id )allocWithZone:( NSZone * )zone {
@synchronized( [ MYSingleton class ] ) {
if( sharedInstance == nil )
sharedInstance = [ super allocWithZone:zone ];
}
return sharedInstance;
}
-( id )init {
@synchronized( [ MYSingleton class ] ) {
self = [ super init ];
if( self != nil ) {
// Insert initialization code here
}
return self;
}
}
@end
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-01-13 22:07:14
Solo quería dejar esto aquí para no perderlo. La ventaja de este es que es utilizable en InterfaceBuilder, que es una gran ventaja. Esto está tomado de otra pregunta que hice :
static Server *instance;
+ (Server *)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 = [[Server hiddenAlloc] init];
}
}
- (id) init
{
if (instance)
return self;
self = [super init];
if (self != nil) {
// whatever
}
return self;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:55:10
static mySingleton *obj=nil;
@implementation mySingleton
-(id) init {
if(obj != nil){
[self release];
return obj;
} else if(self = [super init]) {
obj = self;
}
return obj;
}
+(mySingleton*) getSharedInstance {
@synchronized(self){
if(obj == nil) {
obj = [[mySingleton alloc] init];
}
}
return obj;
}
- (id)retain {
return self;
}
- (id)copy {
return self;
}
- (unsigned)retainCount {
return UINT_MAX; // denotes an object that cannot be released
}
- (void)release {
if(obj != self){
[super release];
}
//do nothing
}
- (id)autorelease {
return self;
}
-(void) dealloc {
[super dealloc];
}
@end
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-03 18:40:09
Sé que hay muchos comentarios sobre esta "pregunta", pero no veo a mucha gente sugiriendo usar una macro para definir el singleton. Es un patrón tan común y una macro simplifica enormemente el singleton.
Aquí están las macros que escribí basadas en varias implementaciones de Objc que he visto.
Singeton.h
/**
@abstract Helps define the interface of a singleton.
@param TYPE The type of this singleton.
@param NAME The name of the singleton accessor. Must match the name used in the implementation.
@discussion
Typcially the NAME is something like 'sharedThing' where 'Thing' is the prefix-removed type name of the class.
*/
#define SingletonInterface(TYPE, NAME) \
+ (TYPE *)NAME;
/**
@abstract Helps define the implementation of a singleton.
@param TYPE The type of this singleton.
@param NAME The name of the singleton accessor. Must match the name used in the interface.
@discussion
Typcially the NAME is something like 'sharedThing' where 'Thing' is the prefix-removed type name of the class.
*/
#define SingletonImplementation(TYPE, NAME) \
static TYPE *__ ## NAME; \
\
\
+ (void)initialize \
{ \
static BOOL initialized = NO; \
if(!initialized) \
{ \
initialized = YES; \
__ ## NAME = [[TYPE alloc] init]; \
} \
} \
\
\
+ (TYPE *)NAME \
{ \
return __ ## NAME; \
}
Ejemplo de uso:
MyManager.h
@interface MyManager
SingletonInterface(MyManager, sharedManager);
// ...
@end
MyManager.m
@implementation MyManager
- (id)init
{
self = [super init];
if (self) {
// Initialization code here.
}
return self;
}
SingletonImplementation(MyManager, sharedManager);
// ...
@end
¿Por qué una macro de interfaz cuando está casi vacía? Coherencia de código entre el encabezado y archivos de código; mantenibilidad en caso de que desee agregar más métodos automáticos o cambiarlo.
Estoy usando el método initialize para crear el singleton como se usa en la respuesta más popular aquí (en el momento de escribir).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-22 20:00:41
Con los métodos de la clase Objective C, podemos evitar usar el patrón singleton de la manera habitual, desde:
[[Librarian sharedInstance] openLibrary]
A:
[Librarian openLibrary]
Envolviendo la clase dentro de otra clase que solo tiene Métodos de clase , de esa manera no hay posibilidad de crear accidentalmente instancias duplicadas, ya que no estamos creando ninguna instancia!
Escribí un blog más detallado aquí :)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-10 22:35:08
Para extender el ejemplo de @robbie-hanson ...
static MySingleton* sharedSingleton = nil;
+ (void)initialize {
static BOOL initialized = NO;
if (!initialized) {
initialized = YES;
sharedSingleton = [[self alloc] init];
}
}
- (id)init {
self = [super init];
if (self) {
// Member initialization here.
}
return self;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-22 16:52:31
Mi camino es simple así:
static id instanceOfXXX = nil;
+ (id) sharedXXX
{
static volatile BOOL initialized = NO;
if (!initialized)
{
@synchronized([XXX class])
{
if (!initialized)
{
instanceOfXXX = [[XXX alloc] init];
initialized = YES;
}
}
}
return instanceOfXXX;
}
Si el singleton ya está inicializado, no se introducirá el bloque de BLOQUEO. El segundo comprobar si (!inicializado) es para asegurarse de que no se inicializa todavía cuando el hilo actual adquiere el BLOQUEO.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-24 06:45:56
No he leído todas las soluciones, así que perdone si este código es redundante.
Esta es la implementación más segura de subprocesos en mi opinión.
+(SingletonObject *) sharedManager
{
static SingletonObject * sharedResourcesObj = nil;
@synchronized(self)
{
if (!sharedResourcesObj)
{
sharedResourcesObj = [[SingletonObject alloc] init];
}
}
return sharedResourcesObj;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-06 19:56:53
Normalmente uso código más o menos similar al de la respuesta de Ben Hoffstein (que también saqué de Wikipedia). Lo uso por las razones expuestas por Chris Hanson en su comentario.
Sin embargo, a veces tengo la necesidad de colocar un singleton en un PLUMÍN, y en ese caso utilizo lo siguiente:
@implementation Singleton
static Singleton *singleton = nil;
- (id)init {
static BOOL initialized = NO;
if (!initialized) {
self = [super init];
singleton = self;
initialized = YES;
}
return self;
}
+ (id)allocWithZone:(NSZone*)zone {
@synchronized (self) {
if (!singleton)
singleton = [super allocWithZone:zone];
}
return singleton;
}
+ (Singleton*)sharedSingleton {
if (!singleton)
[[Singleton alloc] init];
return singleton;
}
@end
Dejo la implementación de -retain
(etc.) para el lector, aunque el código anterior es todo lo que necesita en un entorno de recolección de basura.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-24 04:53:41
La respuesta aceptada, aunque compila, es incorrecta.
+ (MySingleton*)sharedInstance
{
@synchronized(self) <-------- self does not exist at class scope
{
if (sharedInstance == nil)
sharedInstance = [[MySingleton alloc] init];
}
return sharedInstance;
}
Por la documentación de Apple:
... Puede adoptar un enfoque similar para sincronizar los métodos de clase de la clase asociada, utilizando el objeto de clase en lugar de self.
Incluso si usar self funciona, no debería y esto me parece un error de copiar y pegar. La implementación correcta para un método de fábrica de clase sería:
+ (MySingleton*)getInstance
{
@synchronized([MySingleton class])
{
if (sharedInstance == nil)
sharedInstance = [[MySingleton alloc] init];
}
return sharedInstance;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-24 04:56:54