Cuando algo así se conoce como costoso, no significa necesariamente que nunca deba hacerlo, simplemente 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 formateaba los números para mostrar en cada celda (podría agregar, esto fue cuando yo era un principiante en el desarrollo de iOS). Mi primer intento fue la 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 bajó a aproximadamente 15 FPS porque estaba asignando un nuevo NSNumberFormatter
cada vez que se golpeó tableView:cellForRowAtIndexPath:
.
me fijo al cambiar el código para 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 me he cargado con pereza el NSNumberFormatter
en una Ivar, de manera que cada ejecución de tableView:cellForRowAtIndexPath:
ya no se asigna una nueva instancia. Este simple cambio empujó el rendimiento de desplazamiento hasta unos 60 FPS.
Este ejemplo específico ya no es tan relevante, ya que los chips más nuevos son capaces de manejar la asignación sin afectar el rendimiento del desplazamiento, pero siempre es mejor ser lo más eficiente posible.
perfiles es indoloro – justin
Puede perfil de su aplicación para determinar de qué manera se adapte mejor a sus necesidades. Creo que los desarrolladores querían señalar que algo tan inocuo como 'NSDateFormatter' puede tener un código de inicializador bastante complicado, así que aquí hay una pista en la documentación para reutilizar el objeto inicializado tanto como sea posible. –