cellforRowAtIndexPath эффективность? - PullRequest
1 голос
/ 02 января 2012

Всякий раз, когда я прокручиваю свое табличное представление, это очень медленно.Я думаю, это связано с тем, как я загружаю свои клетки.Я использую UINib (5.0+) всякий раз, когда могу, обеспечивая при этом обратную совместимость.Затем я загружаю метки и изображения своей пользовательской ячейки с элементами из NSDictionary из NSArray, который загружается из NSUserDefaults в ViewDidLoad.

Есть ли способ повысить эффективность этого cellForRowAtIndexPath?

- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    CustomCell *cell = (CustomCell *)[aTableView dequeueReusableCellWithIdentifier:@"Cell"];
    if (cell == nil) {
        if ([self labelCellNib]) {
            [[self labelCellNib] instantiateWithOwner:self options:nil];
        } else {
            [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil];
        }
        cell = [self CustomTableCell];
        [self setCustomTableCell:nil];
    }
    NSDictionary *dictionary = [myArray objectAtIndex:indexPath.row];
    NSData *data = [dictionary objectForKey:@"OCRImage"];
    cell.previewPicture.image = [self roundCorneredImage:[UIImage imageWithData:data] radius:60];

    cell.titleLabel.text = [dictionary objectForKey:@"Title"];
    cell.titleLabel.delegate = self;

    cell.dateLabel.text = [dictionary objectForKey:@"Date"];

    if (indexPath.row%2) {
        cell.backgroundImage.image = firstImage;
    }
    else {
        cell.backgroundImage.image = secondImage;
    }
    return cell;
}

Редактировать:

- (UIImage*)roundCorneredImage: (UIImage*)orig radius:(CGFloat) r {
    UIGraphicsBeginImageContextWithOptions(orig.size, NO, 0);
    [[UIBezierPath bezierPathWithRoundedRect:(CGRect){CGPointZero, orig.size} 
                                cornerRadius:r] addClip];
    [orig drawInRect:(CGRect){CGPointZero, orig.size}];
    UIImage* result = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return result;
}

Редактировать2 : эти строки вызывают задержку:

NSData *data = [dictionary objectForKey:@"OCRImage"];
cell.previewPicture.image = [self roundCorneredImage:[UIImage imageWithData:data] radius:60];

Ответы [ 3 ]

3 голосов
/ 02 января 2012

Как сказал @Till в комментарии, вы должны запустить свое приложение в Instruments (Product -> Profile in Xcode) и выбрать инструмент CPU -> Time Profiler.

Затем прокрутите вокруг места в течение нескольких секунд, затем нажмите значок панели инструментов «Запись» на инструментах, чтобы закрыть приложение. Вы сможете увидеть раздел прокрутки, потому что загрузка процессора, вероятно, будет зафиксирована на 100% (если только она не медленная из-за проблем с сетевой активностью).

Нажмите на шкалу времени после начала области высокой активности ЦП, затем нажмите кнопку на панели инструментов «Начать диапазон проверки», затем щелкните до конца области высокой активности ЦП и нажмите кнопку на панели инструментов «Остановить диапазон проверки».

Теперь вы можете перейти к представлению дерева вызовов в нижней части окна, чтобы выяснить, где именно используется ЦП. По моему опыту, обычно легче найти проблему, если отключить опцию «инвертировать дерево вызовов» слева.

Ошибки производительности могут быть очень трудно найти, и иногда строка кода, которая явно медленная, на самом деле не вызывает никаких проблем. Единственный способ исправить проблемы с производительностью, не теряя времени, - это использовать инструменты.

2 голосов
/ 02 января 2012

Убедитесь, что вы установили идентификатор повторного использования для своей ячейки на то же, что вы указали в своем коде, то есть @"Cell".Если они не совпадают, то вы не будете использовать ячейки должным образом и, вероятно, будете тратить гораздо больше времени на создание ячеек, чем необходимо.

Если вы правильно утилизируете ячейки, то вам стоит взглянуть накод после блока if (cell == nil) {...}.Вы пропустите весь этот блок, как только таблица создаст достаточно ячеек, чтобы заполнить экран (и, возможно, еще одну или две), поэтому большая часть времени, связанного с этим методом во время прокрутки, будет связана со следующим кодом.Было бы интересно узнать, что такое myArray, и если это действительно массив, то что делает метод objectForKey:.Ничто иное там не выглядит так, как это должно занять много времени, но лучший способ узнать, куда идут циклы, - это профилировать ваш код в Инструментах.

1 голос
/ 02 января 2012

Некоторые мои заметки после просмотра вашего кода:

  1. Кеширует ли roundCorneredImage:radius: результат?Если нет, то выполнение вызовов CG для каждой ячейки наверняка станет узким местом. Обновлено: Для уверенности используйте инструменты, но может быть быстрее (если память позволяет) хранить обработанную UIImage в коллекции, чтобы вы могли извлечь ее снова при следующем вызове метода с помощьюте же параметры.

  2. Все ваши UIImage могут быть объявлены в другом месте, а затем представлены в этом методе.Ваш текущий код создает новый UIImage для каждой ячейки, что также может ограничить прокрутку. Обновлено: Поскольку Image1.png и Image2.png в основном являются статическими, вы можете объявить их в своем интерфейсе или как статический ivar, а затем просто назначить их фоновому изображению, а не создавать экземпляр UIImage каждый раз.

  3. Может быть быстрее создать подкласс UITableViewCell и создать его, вместо того, чтобы достичь UINib.Кроме того, вы сможете отделить логику макета / данных от метода делегата. Вот суть того, что я сделал в своем UITableViewCell подклассе.По сути, я храню сущность с ячейкой, и ячейка знает о ее метках и тому подобном.Это исключает логику расположения ячеек из моего исходного кода данных.

  4. Похоже, вы используете NSDictionary в качестве источника данных.Если в этом словаре много объектов, может быть значительно быстрее использовать CoreData и NSFetchedResultsController. Вот хороший пост по этому вопросу. Обновлено: Хорошо, это не должно быть проблемой.

-

Редактировать

Так что, если вы удалили всеэто:

NSDictionary *dictionary = [myArray objectForKey:@"OCRImage"];
cell.previewPicture.image = [self roundCorneredImage:[UIImage imageWithData:data] radius:60];

if (indexPath.row%2) {
    cell.backgroundImage.image = firstImage;
}
else {
    cell.backgroundImage.image = secondImage;
}

и все еще отстает, давайте посмотрим на ваши конструкторы ... что делают эти строки?

cell = [self CustomTableCell];
[self setCustomTableCell:nil];

Кроме того, вы не используете прозрачные изображения илиВы что-нибудь в клетке таблицы?Они, как было известно, вызывают задержку рисования ...

-

Edit # 2

Если вы урезаете это, что произойдет?

CustomCell *cell = (CustomCell *)[aTableView dequeueReusableCellWithIdentifier:@"Cell"];
if (cell == nil) {
    if ([self labelCellNib]) {
        [[self labelCellNib] instantiateWithOwner:self options:nil];
    } else {
        [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil];
    }
    cell = [self CustomTableCell];
    [self setCustomTableCell:nil];
}

cell.titleLabel.text = [dictionary objectForKey:@"Title"];
...