Ответ 1
Когда что-то вроде этого называют дорогостоящим, это не обязательно означает, что вы никогда не должны этого делать, это просто означает избежать его в ситуациях, когда вам нужно как можно быстрее выйти из метода. Например, когда 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
в ivar, так что каждый запуск tableView:cellForRowAtIndexPath:
больше не выделяет новый экземпляр. Это простое изменение подтолкнуло производительность прокрутки примерно до 60 FPS.
Этот конкретный пример уже не так важен, поскольку новые чипы способны обрабатывать распределение, не влияя на производительность прокрутки, но всегда лучше быть как можно более эффективным.