iPhone - Оптимизация drawRect - PullRequest
       18

iPhone - Оптимизация drawRect

0 голосов
/ 09 апреля 2011

Я переопределил UIView, чтобы сделать несколько пользовательских рисований:

// ========================================================================================
- (void) drawRect:(CGRect)rect {

    float alphaStep = (kMaxAlpha - kMinAlpha) / (self.nbLines - 1);
    float alphaValue = kMaxAlpha;

    float lineToDrawY = self.headLineYPos;
    float lineWidth = kScanLineMaxWidth;
    float lineWidthStep = (kScanLineMaxWidth - kScanLineMinWidth) / (self.nbLines - 1);

    CGContextRef context = UIGraphicsGetCurrentContext();
    for (int i=1; i<=self.nbLines; i++) {

        CGContextBeginPath(context);
        CGContextSetLineWidth(context, lineWidth);
        CGContextSetStrokeColorWithColor(context, [self.scanColor colorWithAlphaComponent:alphaValue].CGColor);

        CGContextMoveToPoint(context, 0, lineToDrawY);
        CGContextAddLineToPoint(context, [self bounds].size.width, lineToDrawY);
        CGContextStrokePath(context);

        lineToDrawY -= kOneLineJumpDistance;

        lineWidth = MAX(0.5, lineWidth - lineWidthStep);
        alphaValue = MAX(0, alphaValue - alphaStep);
    }
}

self.nbLines может быть около 30-40, может быть 100.

Но эта часть чертежаочень много времени, и я не могу обновлять экран каждые 2 или 3 мс.Это необходимо, чтобы общее время анимации экрана было меньше секунды (я перемещаю линию заголовка каждые xxx мс на xxx пикселей, но слишком большое увеличение приводит к мерцанию).

Как я могу оптимизировать это?

Ответы [ 3 ]

3 голосов
/ 09 апреля 2011

Если вы на самом деле изменяете / анимируете каждый сегмент линии, а не просто добавляете сегмент в конец, то переключение на использование OpenGL ES для вашего чертежа может быть единственным вариантом, который обеспечивает достаточно высокую частоту кадров анимации.На устройствах iOS Open GL будет визуализировать полигоны (линии), используя аппаратные средства графического процессора, а не штриховые линии в программном обеспечении, как это делает рисование CG.

Если вы добавляете или изменяете сегменты ближе к концу, тогда используйте метод композитингаможет работать (используя несколько CALayers), когда вы не рендеринге большой группы сегментов, которые не меняют каждый кадр.

Кроме того, максимальная частота кадров на устройствах iOS составляет 60 Гц, так что выне нужно рендерить чаще один раз каждые 16,6 мс.Повторная визуализация каждые 2 или 3 мс не будет отображаться на дисплее.

1 голос
/ 09 апреля 2011

Я думаю, что есть возможность использовать CoreAnimation, если вы можете разделить изображение на слои, которые только перемещаются друг на друга. AFAIK делает рисование, тогда появляется только один раз, и написание выполняется GPU.

Возможно, вы могли бы нарисовать линию головы, которую нужно анимировать на отдельном слое, а затем анимировать этот слой с помощью CoreAnimation.

Я не уверен, что это полезно в каком-то смысле, так как я не могу представить, что вы рисуете только из кода для рисования.

1 голос
/ 09 апреля 2011

К сожалению, drawRect не лучшее место для анимации. Я думаю, что причина в том, что результат drawRect копируется в новую текстуру (CALayer) и затем отображается на экране.

Если анимация, которую вы хотите сделать, не может быть выполнена с помощью анимации UIView или CoreAnimation, вы можете сделать следующее:

  1. Убедитесь, что вы не вызываете needsDisplay на излишне часто. Когда вы что-то рисуете один раз, результат кэшируется в CALayer, поэтому вызывать drawRect нужно только тогда, когда что-то меняется.

  2. Поскольку вы создаете представление, которое часто обновляется, попробуйте использовать needsDisplayInRect вместо needsDisplay. Затем выполните рефакторинг своего кода, чтобы обновить только часть, переданную в drawRect.

  3. Если вы все еще не получаете нужную вам производительность, вам следует изучить рисование на CGLayer напрямую или использовать библиотеку, например cocos2d

...