Как оптимизировать рендеринг UITableViewCell при использовании CGContextDrawLinearGradient - PullRequest
3 голосов
/ 27 апреля 2011

У меня есть UITableView, где я пытаюсь получить максимально возможную производительность прокрутки.

Ячейка не содержит никаких подпредставлений, все делается методом drawRect.

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

Я могу видеть из использования инструментов, что основная часть (> 50%) времени выполнения при прокрутке происходит от рисования линейного градиента. Фактически почти все это происходит от вызова CGContextDrawLinearGradient.

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

Вот мой код:

- (void)drawRect:(CGRect)rect  
{  
  [self drawCellBackground:rect];  
  [self drawSeparator:rect];  
  ....
}

- (void)drawCellBackground:(CGRect)rect
{
  CGContextRef context = UIGraphicsGetCurrentContext();

  CGColorRef notQuiteWhiteColor = [UIColor colorWithRed:245.0/255.0 green:245.0/255.0 
                                             blue:245.0/255.0 alpha:1.0].CGColor;
  CGColorRef lightGrayColor = [UIColor colorWithRed:235.0/255.0 green:235.0/255.0 
                                             blue:235.0/255.0 alpha:1.0].CGColor;

  drawLinearGradient(context, rect, notQuiteWhiteColor, lightGrayColor);
}

Из отдельного файла .c:

void drawLinearGradient(CGContextRef context, CGRect rect, CGColorRef startColor, CGColorRef  endColor)
{
  CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
  CGFloat locations[] = { 0.0, 1.0 };

  NSArray *colors = [NSArray arrayWithObjects:(id)startColor, (id)endColor, nil];

  CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, 
                                                  (CFArrayRef) colors, locations);

  CGPoint startPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect));
  CGPoint endPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect));

  CGContextSaveGState(context);
  CGContextAddRect(context, rect);
  CGContextClip(context);
  CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);
  CGContextRestoreGState(context);

  CGGradientRelease(gradient);
  CGColorSpaceRelease(colorSpace);
}

Ответы [ 2 ]

4 голосов
/ 27 апреля 2011

Если вы абсолютно хотите придерживаться drawRect: (который, я считаю, дает лучшую производительность, чем отдельные представления на старых устройствах), почему бы не перенести ваш градиент в CGImage или UIImage, тогда используйте это для рисования в -drawRect:?

Кроме того, вы можете заранее создать свой градиент:

static CGGradientRef GetCellBackgroundGradient()
{
    static CGGradientRef gradient = NULL ;
    if ( !gradient )
    {
        gradient = // create your CGGradientRef here
    }

    return gradient;
}

Для высокопроизводительного кода вы хотите предварительно выделить как можно больше вещей (памяти / объектов).

2 голосов
/ 27 апреля 2011

Правильно ли вы используете ячейки табличного представления?Если так, то в этом случае я думаю, что вам будет лучше использовать подпредставления в табличном представлении вместо того, чтобы рисовать все в drawRect:.Используя подпредставления и предполагая, что градиент одинаков для всех ячеек, градиент должен быть нарисован только один раз для повторно используемой ячейки.Когда он будет переработан с новым контентом, потребуется обновить только текстовые и графические представления вместо того, чтобы заново рисовать градиент.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...