2011-06-20 19 views
9

Mi equipo descubrió que estábamos utilizando una variedad de objetos NSDateFormatter en toda nuestra base de códigos, y comenzamos a investigar cómo podríamos evitar el costo/confusión de asignar/inicializar formateadores comunes en un grupo de lugares separados.NSDateFormatter compartido: ¿mejores prácticas?

Una idea que tuvimos fue crear una categoría en la clase NSDateFormatter que proporcionaría una referencia a una instancia estática de un formateador comúnmente configurado. Por ejemplo, estábamos usando el "corto tiempo" fecha del formateador en varios lugares, y estaban buscando para añadir el siguiente método de la clase:

@implementation NSDateFormatter (NSDateFormatter_PDDateFormatters) 

static NSDateFormatter * shortTimeFormatter = nil; 

+ (NSDateFormatter *) PDSharedShortTimeFormatter { 

    @synchronized([NSDateFormatter class]){ 

     if(shortTimeFormatter == nil){ 

      // Create new formatter for SHORT times (e.g. 12:00 pm) 

      shortTimeFormatter = [[NSDateFormatter alloc] init]; 
      [shortTimeFormatter setDateStyle: NSDateFormatterNoStyle]; 
      [shortTimeFormatter setTimeStyle:NSDateFormatterShortStyle]; 
     } 

     return shortTimeFormatter; 

    } 

    return nil; 
} 

@end 

Uno de los problemas que tengo con este enfoque es que no estamos actualmente " proteger "el NSDateFormatter de ser cambiado. Debido a que el formateador es esencialmente "compartido" en toda nuestra aplicación, esto podría causar problemas si otro objeto cambiara la configuración del formateador (por ejemplo, estilo de hora/fecha).

Como estamos utilizando esto internamente, no estoy demasiado preocupado con el riesgo de que nuestro equipo abuse de esta funcionalidad (es decir, es un equipo pequeño y claramente comentado).

Sin embargo, me preguntaba acerca de las mejores prácticas aquí.

¿Hay alguna forma de devolver una referencia inmutable al formateador de fecha? Si devuelvo una copia de un formateador, ¿es menos costoso que hacer los alloc/inits que estamos haciendo ahora?

¿Hay algún otro enfoque para tomar aquí?

Estaremos funcionando con esto, pero siempre es bueno obtener algunos comentarios al escribir el código "mejor".

Respuesta

9

Normalmente, simplemente no te preocupes por eso. Obj-C te permitirá jugar con el interior jugoso de casi cualquier cosa. Incluso @private no protege contra -valueForKey:_thatFunPrivateIvar. Y si todo lo demás falla, puede invocar las funciones de tiempo de ejecución.

Sin embargo, la solución más simple aquí sería exponer una API que utiliza internamente formateadores almacenados en caché, pero que no proporciona acceso a los formateadores que está utilizando. Su código luego usaría +[Formatter shortTimeStringFromDate:] para hacer lo que su código de muestra está haciendo ahora. El formateador en cuestión podría asignarse de forma perezosa, y podría usar memoria purgable para que los formateadores almacenados en caché se puedan borrar en modo LRU bajo la presión de la memoria.

+0

En este caso particular, también he pensado agregar una API "pública" a la clase 'NSDate':' [date PDShortTime] '. Entonces, el objeto 'NSDateFormatter' almacenado en caché solo se accede detrás de las escenas. ¡Gracias por la respuesta! – thauburger

+0

Esto también sería bueno como una categoría en NSString es decir/[NSString shortTimeFromDate:] – ADAM

+0

"Simplemente no te preocupes por eso" no es el camino a seguir: es increíblemente fácil modificar objetos accidentalmente. Definitivamente hacer la solución, que es una gran solución. –