singleton-uml

Cómo crear un Singleton en Objective C y Cocoa

Singleton en Cocoa y Objective C

Aunque el Singleton parece que se estuviese convirtiendo en el apestado de moda, como el goto de antaño,
no hay motivos suficientes para mandarlo al «pasillo de la muerte».

Los principales argumentos contra el uso de un Singleton parecen ser:

  1. Seguridad en código multihebra: Coño, sólo si lo implementas mal.
  2. Vulnera el principio de una única responsabilidad por clase: Psé, no soy muy fundamentalista que digamos…
  3. Rendimiento en código multitarea: Dudo mucho que el entrar y salir de un @synchronized sea tu principal cuello de botella, por mucho que hayas abusado del número de singletons.

Además, en casos en que se necesita representar objetos únicos, ya sea dispositivos físicos o recursos de red, un Singleton es la técnica más adecuada.

Implementación básica de un Singleton en Objective C y Cocoa

Una implementación segura y que no hace uso de variables globales sería:

  1. #import «MySingleton.h»
  2. @implementation MySingleton
  3. +(MySingleton *) sharedInstance{
  4.     static  MySingleton *inst = nil;
  5.     @synchronized(self){
  6.         if (!inst) {
  7.             inst = [[self alloc] init];
  8.         }
  9.     }
  10.     return inst;
  11. }
  12. @end

Gestión de memoria del Singleton

¿Cuando será liberada la instancia estática? A no ser que algún código erróneo sobre libere dicha instancia, sobrevivirá hasta el fin de la aplicación. Si representa algo que puede ser desconectado (un recurso de red o dispositivo físico), la clase debería de observar la notificación correspondiente. Ver «Cocoa Design Patterns» para más detalles.

Implementación Completa del Singleton

La implementación básica no impide que el código cliente pueda crear otras instancias. Si hace falta llegar a esos extremos, habría que sobreescribir todos los métodos de creación:alloc, copy, new.

Otras implementaciones

En StackOverflow, se citan otras muchas implementaciones. la mayoría son seguras en multitarea y hacen grandes esfuerzos para minimizar el coste de sincronización. Probablemente se trate de optimización prematura, pero hay algunas técnicas interesantes, como la aportada por kendall que usa «method-swizzling«.

Si realmente el código de sincronización es un cuello de botella, una implementación alternativa, rápida y sencilla que usa dispatch_once sería:

  1. +(MyClass *)singleton {
  2.  static dispatch_once_t pred;
  3.  static MyClass *shared = nil;
  4.  dispatch_once(&pred, ^{
  5.   shared = [[MyClass alloc] init];
  6.  });
  7.  return shared;
  8. }

 

Fernando Rodríguez

Sígueme en twitter.
Cursos de desarrollo iPhone

Acerca de Fernando Rodriguez

Fundador & Editor Jefe de justcodeit, Fernando Rodríguez (@frr149 & Linkedin) es desarrollador & un experto en la enseñanza de máxima calidad en programación y desarrollo para dispositivos iOS, Cocoa Touch, Objective C, Swift, Python, entre otros, aunque su mejor carta de presentación, es la opinión de sus alumnos: http://keepcoding.io/es/testimonio/ CLO en KeepCoding & Arunovo. Instructor de iOS Avanzado del Big Nerd Ranch. Profesor Asociado de la U-tad, autor invitado de revistas como iPhoneWorld, Applesfera.com & ponente habitual en conferencias dentro y fuera de España (iOSDevUK, CodeMotion, BCNDevCon, etc). En sus vidas anteriores fue un nerd de Python y Django, mago de Smalltalk, y para su pesar, galeote de C++ y un gran cocinero.

Share this:

Leave a comment