Когда что-то подобное называют дорогостоящим, это не обязательно означает, что вы никогда не должны этого делать, это просто означает, что следует избегать этого в ситуациях, когда вам нужно как можно быстрее выйти из метода.Например, когда iPhone 3G был самым последним устройством, я писал приложение с UITableView
, которое форматировало числа для отображения в каждой ячейке (я мог бы добавить, что это было еще тогда, когда я был новичком в разработке iOS).Моей первой попыткой было следующее:
- (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;
}
Производительность прокрутки этого кода была ужасна. Частота кадров упала примерно до 15 FPS, потому что я каждый раз выделял новый NSNumberFormatter
tableView:cellForRowAtIndexPath:
был поражен.
Я исправил это, изменив код на это:
- (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;
}
Разница здесь в том, что я лениво загрузил NSNumberFormatter
в ивар, поэтомучто каждый прогон tableView:cellForRowAtIndexPath:
больше не выделяет новый экземпляр.Это простое изменение подняло производительность прокрутки примерно до 60 FPS.
Этот конкретный пример уже не так актуален, так как более новые чипы способны обрабатывать выделение, не влияя на производительность прокрутки, но всегда лучшебыть максимально эффективным.