views:

130

answers:

2

I have a chart drawn with CoreGraphics.

This chart can be scrolled horizontally and it's drawn as we scroll it.

The problem is that on 3G/3GS the speed and performance of the scroll is good but on iPhone 4 is slower than expected.

I suppose this is a issue related to the higher resolution of the iPhone 4. Is that correct?

How can I increase the performance on iPhone 4? Does the framework automatic conversion to draw on iPhone 4 resolution or is it my work?

Thank you very much.

A: 

The experience "it is slower", could you describe it more accurately? I'll assume that the frame-rate of the scroll has been lowered to where it doesn't look smooth or even stutters.

If so, and if you're certain that it's the resolution that is the cause of this, there are two general methods I can see.

  • update at for example half the interval, rendering half as wide slices. If Cocoa Touch doesn't facilitate that, you could trigger a callback at a timed interval from the rendering method you have now.
  • render "further in advance" so that a part of the graph hidden further outside the viewable area is rendered when it's scrolled into view.

I'm assuming you've already looked at the "Drawing" properties of the view, Opaque etc as they do affect performance.

Henrik Erlandsson
+3  A: 

The iPhone 4 can be much slower when it comes to CoreGraphics processing.

One possible idea for your case. When the user is scrolling, rather than draw full resolution, draw your CoreGraphics related stuff a half resolution context. Then take that context as a bitmap and scale it up to full resolution. This would be for iPhone4 only and you would lose the nice higher resolution quality, but only be while the user is scrolling.

Here's some code I wrote up for testing between the different devices.

My results when displaying the view at full screen.

  • 3G, 9 FPS
  • 3GS, 16 FPS
  • i4, 5 FPS (bummer)

CoreGraphicsTestView.h

#import <UIKit/UIKit.h>
@interface CoreGraphicsTestView : UIView 
{
    int displayCounter;
    float displayInterval;
    char fps[50];
}
@end

CoreGraphicsTestView.m

#import "CoreGraphicsTestView.h"
#define RNDN(s, e) ((((CGFloat)rand() / (CGFloat)INT_MAX) * ((e)-(s)) + (s)))
#define RNDX(s, e, r) (RNDN((s), (e)) * (r).size.width)
#define RNDY(s, e, r) (RNDN((s), (e)) * (r).size.height)
#define RNDR(r) (CGRectMake(RNDX(0,0.50,(r)),RNDY(0,0.50,(r)),RNDX(0.50,1.0,(r)),RNDY(0.50,1.0,(r))))
@implementation CoreGraphicsTestView
- (id)initWithFrame:(CGRect)frame 
{
    if ((self = [super initWithFrame:frame])) 
    {
        self.backgroundColor = [UIColor blackColor];
        srand(time(NULL));
        fps[0] = '\0';
    }
    return self;
}
- (void)updateDisplayCounter:(CGContextRef)c rect:(CGRect)rect
{
    displayCounter++;
    float now = (float)clock() / (float)CLOCKS_PER_SEC;
    if (now - displayInterval > 1)
    {
        sprintf(fps, "%0.0f", displayCounter / (now - displayInterval));
        printf("%s\n", fps);
        displayInterval = now;
        displayCounter = 0;
    }
    CGContextTranslateCTM(c, 5, 40);
    CGContextScaleCTM(c, 1.0, -1.0); 
    CGContextSetFillColorWithColor(c, [UIColor whiteColor].CGColor);
    CGContextSelectFont(c, "Arial", 18, kCGEncodingMacRoman);
    CGContextShowTextAtPoint(c, 0, 0, fps, strlen(fps));
}
- (void)setRandomColor:(CGContextRef)c
{
    CGFloat components[4] = {1,RNDN(0, 1),RNDN(0, 1),RNDN(0, 1)};
    CGContextSetFillColor(c, components);
}
- (void)drawRect:(CGRect)rect
{
    CGContextRef c = UIGraphicsGetCurrentContext(); 
    for (int i=0;i<5;i++)
    {
        [self setRandomColor:c];
        CGContextFillRect(c, RNDR(rect));
        [self setRandomColor:c];
        CGContextFillEllipseInRect(c, RNDR(rect));
    }
    [self updateDisplayCounter:c rect:rect];
    [self performSelector:@selector(setNeedsDisplay) withObject:nil afterDelay:0.0];
}
@end
jojaba