example - Patrón singleton Objective-C en iOS 5+
singleton swift 3 (5)
He estado leyendo muchos hilos y artículos de blog sobre cómo implementar un singleton en Object-C, varios de ellos tal vez un poco obsoletos (año 2010 o anterior), y parece que las personas tienen opiniones diferentes con respecto a este tema. ¿Apple tiene documentación sobre la implementación de un singleton? No pude encontrarlo Si es así, ¿podría alguien decirme dónde?
Necesito un singleton para una clase que tiene algunas variables tanto públicas como privadas. Actualmente, esta es la implementación que tengo para dicha clase:
@interface MySingleton ()
@property (strong, nonatomic) NSString *state;
@end
@implementation MySingleton
@synthesize state = _state;
@synthesize count = _count;
static MySingleton *sharedObject = nil;
+ (MySingleton *)sharedInstance
{
static dispatch_once_t _singletonPredicate;
dispatch_once(&_singletonPredicate, ^{
sharedObject = [[super allocWithZone:nil] init];
});
return sharedObject;
}
+ (id)allocWithZone:(NSZone *)zone
{
return [self sharedInstance];
}
¿Debería ser esta la forma recomendada? ¿Y cómo debo inicializar las variables de instancia, públicas y privadas?
Otro problema que me gustaría aclarar sobre singleton es: ¿generará esto una pérdida de memoria? ¿El uso de singletons realmente se recomienda en iOS?
Gracias
Sí, esta es la forma recomendada. Solo hay una pequeña diferencia de cómo la uso: defino el sharedObject
como una variable estática dentro del método + (MySingleton *)sharedInstance
, porque no debería ser posible acceder a la variable desde ningún otro lado, sino desde el método getter.
Y no, no crearás una pérdida de memoria. Cuando finalice su aplicación, toda la memoria reservada utilizada por su aplicación se lanzará de todos modos y no hay otra situación en la que una instancia compartida estática deba ser liberada. En el área previa al ARC, incluso era común anular el método de release
, evitando la liberación accidental del objeto.
En Xcode, en ''Buscar documentación'', ingrese Crear una instancia Singleton . Hay muchos resultados (pero el enlace de arriba, en la parte inferior de la página, tiene código de ejemplo).
Lo anterior es correcto, junto con el comentario de @ miho sobre incluir el objeto estático dentro del método sharedInstance. Pero no hay razón para anular +allocWithZone:
Los singletons en ObjC generalmente son "compartidos", no forzados. Eres libre de crear otras instancias de "singleton". Si es ilegal crear otras instancias, entonces debe hacer que init
realice un NSAssert
lugar de engañar a la persona que llama en +allocWithZone:
Si su singleton es mutable (y la mayoría lo son), no debería anular +allocWithZone:
esta manera.
Otro problema que me gustaría aclarar sobre singleton es: ¿generará esto una pérdida de memoria?
No. Este objeto nunca se lanzará, pero siempre estará accesible. Eso no es una pérdida.
¿El uso de singletons realmente se recomienda en iOS?
Sí, y es un patrón muy común, utilizado en todos los marcos de Cocoa. Dicho esto, hay varios otros patrones que recientemente comenzaron a ser populares entre los desarrolladores. La Inyección de Dependencia está adquiriendo cierto interés, aunque no la veo en la práctica muy a menudo. La reducción de su dependencia de los singletons puede mejorar la capacidad de prueba, y he estado experimentando recientemente con la forma de eliminar algunos de ellos en mi código con cierto éxito. Pero tienen una larga y orgullosa historia en Cocoa, y no los considero un problema.
EDITAR: tienes un error real en tu código. Debería llamar a [[self alloc] init]
, no a [[super alloc] init]
. No hay ninguna razón para llamar a +allocWithZone:
solo use +alloc
. (El tiempo cuando ...WithZone:
métodos fueron útiles ya pasó).
Todavía uso el encabezado singleton de CocoaWithLove , puede que sea un poco anticuado, pero sigue funcionando como un amuleto. Básicamente hace lo mismo que se describe aquí, refiriéndose a la documentación de Apple y supongo que al menos la documentación de Apple (al final de esta página ) sigue siendo válida. Hay personas que suponen que permanecerá válido indefinidamente ya que es la solución oficial que sugirió Apple.
Un poco de advertencia usando gcd para singletons:
dispatch_once(&_singletonPredicate, ^{
sharedObject = [[super allocWithZone:nil] init];
});
si el método init aborda por algún motivo el objeto singleton directa o indirectamente, habrá un punto muerto. Por esta razón, creo que la forma más apropiada de escribir un singleton es mediante el
+ (void) initialize
método