objective example ios nsdateformatter

ios - example - nsdateformatter objective c



¿Por qué la asignación o inicialización de NSDateFormatter se considera "costosa"? (2)

¿Qué quiere decir la gente cuando dice que esto es caro? Creo instancias de muchos objetos transitorios solo para almacenamiento intermedio (NSString y NSDate son los típicos). ¿Cómo puedo saber si el uso de NSDateFormatter en mi programa lo está exagerando?

Hasta ahora, he tendido a crear lo que equivale a un singleton, pero mi preferencia sería encapsularlo en algunos de los otros objetos con los que está asociado para poder usar las referencias propias.

A falta de ejecutar pruebas de rendimiento, busco una mejor "regla de oro" para comprender por qué debo o no hacer esto.


Cuando algo como esto se denomina caro, no significa necesariamente que nunca deba hacerlo, solo significa evitar hacerlo en situaciones en las que necesita salir de un método lo más rápido posible. Por ejemplo, cuando el iPhone 3G era el último dispositivo, estaba escribiendo una aplicación con un UITableView que UITableView formato a los números para mostrar en cada celda (podría agregar, esto fue cuando era un principiante en el desarrollo de iOS). Mi primer intento fue el siguiente:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { NSString *reuseIdentifier = @"cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier forIndexPath:indexPath]; MyManagedObject *managedObject = [self.managedObjects objectAtIndex:indexPath.row]; NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init]; [numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle]; [cell.textLabel setText:[managedObject title]]; [cell.detailTextLabel setText:[numberFormatter stringFromNumber:[managedObject amount]]]; return cell; }

El rendimiento de desplazamiento de este código fue terrible. La velocidad de fotogramas se redujo a aproximadamente 15 FPS porque estaba asignando un nuevo NSNumberFormatter cada vez que se tableView:cellForRowAtIndexPath:

Lo arreglé cambiando el código a esto:

- (NSNumberFormatter *)numberFormatter { if (_numberFormatter != nil) { return _numberFormatter; } _numberFormatter = [[NSNumberFormatter alloc] init]; [_numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle]; return _numberFormatter; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { NSString *reuseIdentifier = @"cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier forIndexPath:indexPath]; MyManagedObject *managedObject = [self.managedObjects objectAtIndex:indexPath.row]; NSNumberFormatter *numberFormatter = [self numberFormatter]; [cell.textLabel setText:[managedObject title]]; [cell.detailTextLabel setText:[numberFormatter stringFromNumber:[managedObject amount]]]; return cell; }

La diferencia aquí es que he cargado perezosamente el NSNumberFormatter en un ivar, de modo que cada ejecución de tableView:cellForRowAtIndexPath: ya no asigna una nueva instancia. Este simple cambio elevó la copia de seguridad del rendimiento hasta aproximadamente 60 FPS.

Este ejemplo específico ya no es tan relevante, ya que los nuevos chips son capaces de manejar la asignación sin afectar el rendimiento del desplazamiento, pero siempre es mejor ser lo más eficiente posible.


Tuve esta misma pregunta hace algún tiempo. He ejecutado Instruments en alguna aplicación en la que estaba trabajando y descubro que los desarrolladores anteriores estaban creando un nuevo NSDateFormatter para cada registro personalizado que hicieron. Ya que para cada pantalla solían registrar alrededor de 3 líneas. La aplicación solía dedicar aproximadamente un segundo a la creación de NSDateFormatters.

La solución simple sería conservar la instancia del formateador de fecha en su clase como un atributo o algo y reutilizarla para cada línea de registro.

Después de un pensamiento trivial, vine con una "fábrica" ​​para manejar la reutilización de NSDateFormatters según el formato y la ubicación deseada. Solicito un formateador de fecha de algún formato y configuración regional y mi clase me entrega el formateador ya cargado. Buen ajuste de rendimiento, deberías intentarlo.

PD: Tal vez alguien quisiera probarlo, así que lo hice público: https://github.com/DougFischer/DFDateFormatterFactory/blob/master/README.md