2012-03-07 11 views
5

Bastante temprano en mi aplicación, cuando tenía mucha menos experiencia que ahora, quería darle vida a algunas transiciones entre los controladores de vista con mis propias animaciones personalizadas. Sin tener idea de por dónde empezar, busqué un patrón como MVC al que se pudiera acceder desde casi cualquier controlador en cualquier momento, y resulta que un singleton era el camino a seguir.¿Elegir un singleton o una categoría?

Lo que no me di cuenta es que parece haber un odio fuerte y bien defendido sobre el patrón singleton, y yo mismo estoy empezando a ver por qué, pero eso no viene al caso.

Así que, un tiempo después, decidí mover mi misma implementación a una categoría en UINavigationController (después de todo, maneja las transiciones), mantuve las clases originales para comparar, y me pregunto qué método funcionaría mejor. Después de haber probado exhaustivamente ambas implementaciones, puedo decir sin lugar a dudas que son iguales en todos los sentidos, incluida la velocidad, precisión, suavidad, velocidad de fotogramas, uso de memoria, etc. ¿cuál es "mejor" en el sentido de mantenibilidad general?

EDIT: Después de leer los argumentos bien escritos que todos ustedes han hecho, he decidido usar un singleton. @JustinXXVII ha hecho el argumento más convincente (en mi humilde opinión), aunque considero que cada respuesta aquí es igualmente digna de mérito. Gracias a todos por sus opiniones, he votado por encima de todas las respuestas en la pregunta.

+0

No estoy seguro de por qué los que responden a esta pregunta no parecen entender qué es una categoría. Es una parte del lenguaje de Objective C: http://macdevelopertips.com/objective-c/objective-c-categories.html – johnbakers

+0

@ThomasW, las categorías son una forma de extender las clases de ObjC. Mientras que en los viejos tiempos (ObjC1) se usaban para manejar cosas que usamos protocolos hoy, son algo separado (y muy útil. Https://developer.apple.com/library/ios/#documentation/cocoa/ conceptual/objectivec/chapters/occategories.html –

Respuesta

3

Haré el caso de un objeto singleton. Los singletons se usan en UIKit y iOS. Una cosa que no puedes hacer con las categorías es agregar variables de instancia. Hay dos cosas acerca de esto: los flujos de trabajo

  1. MVC no toleran los objetos con un profundo conocimiento de otros objetos
  2. A veces sólo necesita un lugar para hacer referencia a un objeto que no pertenece realmente en otro sitio

Estas cosas van una contra la otra, pero la capacidad adicional de poder mantener una variable de instancia que realmente no tiene un "propietario" es por qué yo prefiero el singleton.

Normalmente tengo una clase singleton en todos mis proyectos XCode, que se usa para almacenar objetos "globales" y hacer cosas mundanas con las que no quiero cargar mi AppDelegate.

Un ejemplo sería serializar/archivar objetos y desarchivar/restaurar. Tengo que usar el mismo método en varias clases, no quiero extender UIViewController con algún método de serialización para escribir y leer archivos arbitrarios. Quizás es solo mi preferencia personal.

También podría necesitar una forma rápida de buscar información en NSUserDefaults, pero no quiero escribir siempre [[NSUserDefaults standardUserDefaults]stringForKey:@"blah"], así que solo declararé un método en mi singleton que tome un argumento de cadena.

Hasta ahora, no había pensado demasiado sobre el uso de una categoría para estas cosas. Sin embargo, una cosa es segura: prefiero no crear un nuevo objeto cien veces para hacer la misma tarea cuando puedo tener solo un objeto vivo que se queda y me ocupo de las cosas. (Sin cargar AppDelegate)

+0

¡Ahora hay una respuesta! – CodaFi

+0

Pensé más sobre esto ayer y estoy viendo el mejor lado de usar una categoría. Se ajusta mejor a su implementación que un singleton. – Justin

6

Creo que la mejor opción es usar la categoría.

Porque si ya está utilizando UINavigationController, no tiene sentido crear una nueva clase que sólo se encargará de la transición, al igual que le dijo: (after all, it handles transitions!)

Esta será una mejor opción para mantener su código, y usted asegúrese de que la cosa haga lo que espera hacer, y si ya tiene una instancia que hace las transiciones, ¿por qué crear otra?

Los patrones de diseño, como singleton, fábrica y otros, deben utilizarse con responsabilidad. En su caso, no veo por qué usar un singleton, lo usa solo para no crear instancias de objetos nuevos, realmente no necesita tener solo una instancia del mismo, pero lo hace porque solo quiere uno.

1

Singletons, como su nombre lo indica, tiene que ser utilizado cuando hay una necesidad de ser exactamente un objeto en su aplicación. El patrón para el método de acceso asegura que sólo este requisito de ser un método de clase:

+ (MyClass*) sharedInstance 
{ 
    static MyClass *instance = nil; 
    if (instance == nil) instance = [[MyClass alloc] init]; 
    return instance; 
} 

Si se aplica bien, la clase también se asegura de que su constructor es, por tanto privada nadie más puede crear una instancia de la clase, pero el método de acceso: esto asegura que en cualquier momento como máximo existe una instancia de la clase. El mejor ejemplo de dicha clase es UIApplication ya que en cualquier momento puede haber un solo objeto de esta clase.

El punto aquí es que este es el único requisito para singleton. La función del método de acceso es garantizar que solo haya una instancia, y no que proporcione acceso a esa instancia desde cualquier lugar. Es solo un efecto secundario del patrón que, como el método de acceso es estático, todos pueden acceder a este único objeto sin tener una referencia (puntero) a priori. Desafortunadamente, este hecho es ampliamente utilizado por los programadores de Objective C y esto lleva a un diseño desordenado y al odio hacia el patrón singleton que usted mencionó. Pero, en general, no es culpa del simple golpeteo sino del mal uso de su método de acceso.

Volviendo ahora a su pregunta: si no necesita variables estáticas/globales en su código de transición personalizado (supongo que no), entonces la respuesta es definitivamente ir por categorías. En C++, usted podría crear una subclase a partir de una clase primaria BaseTransition e implementar sus propios métodos de dibujo. Objective C tiene categorías (que en mi opinión es otra manera de confundir el diseño fácilmente, pero son mucho más prácticas) en las que puede agregar funcionalidad personalizada, incluso accediendo a las variables de su clase de host. Úselos siempre que pueda canjear singletons con ellos y no use singletons cuando el requisito principal para su clase no sea que sea solo una instancia de este.

2

En esta implementación, para la cual no es necesario usar un Singleton, puede que no haya ninguna diferencia. Eso no quiere decir que no hay uno.

Una cubeta de plástico contiene tanta agua como una cubeta de metal, y lo hace igual de bien. En ese aspecto, parece que no hay diferencia entre los dos. Sin embargo, si intenta transportar algo extremadamente caliente, el cubo de plástico podría no funcionar tan bien ...

Lo que estoy tratando de decir es que ambos sirven a sus propósitos, pero en su caso no parecía haber ningún diferencia porque la tarea era demasiado genérica. Querías un método que estuviera disponible en múltiples clases, y ambas soluciones pueden hacer eso.

En su caso, sin embargo, podría ser mucho más simple usar una Categoría. La implementación es más fácil y usted (posiblemente) necesita menos código.

Pero si fuera a crear un administrador de datos que contenga una matriz de objetos que SOLAMENTE desea que estén disponibles en un solo lugar, una Categoría no estará a la altura de la tarea. Esa es una tarea típica de Singleton. Los singeltons son objetos de instancia única (y si se hacen estáticos, están disponibles desde prácticamente cualquier lugar). Las categorías son extensiones de sus clases existentes y se limitan a la clase que abarca.

Para responder a su pregunta; elige una categoría.

* Una subclase también podría funcionar, pero tiene sus propias ventajas y desventajas

2

¿Por qué no basta con crear una subclase UIViewController de base y se extienden a todas sus controladores de vista de este objeto? Una categoría no tiene sentido para este propósito.

+0

Calendario apretado de lanzamiento + 108 clases y conteo = van a trabajar en esto más tarde. – CodaFi

+0

Buscar y reemplazar? ": UIViewController" con ": BaseViewController". – Sam

+0

Estoy profundamente atrincherado en la etapa de corrección de errores de la próxima versión. Simplemente no tengo tiempo para escribir , luego depurar, una nueva clase. – CodaFi

3

creo que la pregunta real es en el "diseño" (como usted ha dicho, ambos códigos funcionan bien), y anotando su problema en oraciones simples, usted encontrará su respuesta:

  • Singleton El objetivo es tener solo una instancia de una clase ejecutándose en su aplicación. Entonces puedes compartir cosas entre objetos. (uno disponible para muchos objetos)

  • categoría propósito es extender los métodos disponibles a una clase. (Disponible a una clase de objetos solamente! Bien ... objetos de las subclases también)

lo que realmente quiere es hacer una nueva transición a disposición de la clase UINavigationController. UINavigationController, que ya tiene algún método disponible para cambiar la vista (vistas modales modales, viewsubviews, etc.) está diseñado para administrar vistas con transiciones (usted mismo lo dijo, maneja las transiciones), todo lo que desea hacer es agregar otra forma de manejo de transiciones para sus controladores de navegación por lo tanto, usted preferiría utilizar una categoría.

Mi opinión es que lo que quiere lograr está cubierto por la categoría y al hacerlo se asegura de que los únicos objetos que acceden a este método tengan derecho a usarlo. Con el patrón singleton, cualquier objeto de cualquier clase podría llamar a su singleton y sus métodos (y ... podría funcionar, sin saber cómo para una versión de sistema operativo n, pero su aplicación podría romperse en la versión n + 1).