Подтвердить что ты не робот

Почему выделение или инициализация NSDateFormatter считается "дорогим"?

Что люди говорят, когда говорят, что это дорого? Я создаю экземпляры множества переходных объектов только для промежуточного хранилища (типичны NSString и NSDate). Как узнать, перегружает ли моя программа NSDateFormatter?

До сих пор я имел тенденцию создавать то, что составляет одноэлемент, но мое предпочтение заключалось бы в том, чтобы инкапсулировать его в некоторые из других объектов, с которыми он связан, поэтому я могу использовать собственные ссылки.

Заканчивая тесты производительности, я ищу лучшее "правило большого пальца" понимания того, почему я должен или не должен этого делать.

4b9b3361

Ответ 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.

Этот конкретный пример уже не так важен, поскольку новые чипы способны обрабатывать распределение, не влияя на производительность прокрутки, но всегда лучше быть как можно более эффективным.

Ответ 2

У меня был такой же вопрос когда-то. Я запускал инструменты на каком-то приложении, в котором работал, и я полагаю, что предыдущие разработчики создавали новый NSDateFormatter для каждого пользовательского журнала, который они делали. Так как для каждого экрана они использовали для регистрации около 3 строк. Приложение тратило около одной секунды, создавая только NSDateFormatters.

Простое решение сохранит экземпляр форматирования даты в вашем классе как атрибут или что-то еще и повторное его использование для каждой строки журнала.

После некоторого тривиального мышления я пришел с "factory" для обработки повторного использования NSDateFormatters в зависимости от формата и локали. Я прошу форматировать даты в каком-то формате и локали, и мой класс предоставит мне уже загруженный форматтер. Хорошая настройка производительности, вы должны попробовать.

PS: Может быть, кто-то хотел бы протестировать его, поэтому я сделал его общедоступным: https://github.com/DougFischer/DFDateFormatterFactory/blob/master/README.md