views:

1641

answers:

3

Hi,

I am writing an iPhone application in Objective-C that utilizes some custom drawing in views and I would like to benchmark various revisions of my code to see what really helps. I was planing on doing this by setting up a new application, adding my custom drawing code to the drawRect: method of the view, then, in a for loop in the view controller, sending [UIView setNeedsDisplay] some large number of times and timing how long it takes to complete. However the setNeedsDisplay calls seem to be cached so even though I call it 1000 times in a for loop, the drawRect: method gets called only once. Also, I tried calling drawRect: directly but I need a graphics context to do some drawing in and when I don't use setNeedsDisplay: UIGraphicsGetCurrentContext() doesn't give me a context.

Any suggestions?

Thanks,

Kyle

A: 

Inside of your NSView's .m. Obviously you might want to hook this up to a UI or something.

- (void)awakeFromNib {
    // Have to wait for the window to be onscreen, graphics context ready, etc
    [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerFired:) userInfo:NULL repeats:NO];
}


- (void)timerFired:(NSTimer *)aTimer {
    [self lockFocus];

    NSDate* then = [NSDate date];

    int callIdx = 0;
    for( callIdx = 0; callIdx < 1000; callIdx++ ) {
     [self drawRect:[self bounds]];
    }
    NSDate* now = [NSDate date];

    [self unlockFocus];

    NSLog(@"Took %f seconds", [now timeIntervalSinceDate:then]);
}

- (void)drawRect:(NSRect)rect {
    [[NSColor redColor] set];
    NSRectFill(rect);
}
Steven Canfield
lockFocus doesn't appear to be available on UIViews, also, I need some way of getting a graphics context to draw to in my drawRect: function, setNeedsDisplay provides one through UIGraphicsGetCurrentContext() but calling drawRect: directly doesn't seem to do the same thing.
Kyle
+4  A: 

You can benchmark a view by doing the following:

- (NSTimeInterval)timeTakenToDrawView:(UIView *)view count:(NSInteger)count
{
    CGRect bounds = [view bounds];
    NSDate *startDate = [NSDate date];
    UIGraphicsBeginImageContext(bounds.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    NSInteger i = 0;
    for (i = 0; i < count; i++) {
        CGContextSaveGState(context);
        [view drawRect:bounds];
        CGContextRestoreGState(context);
    }
    UIGraphicsEndImageContext();
    return [[NSDate date] timeIntervalSinceDate:startDate];
}

(Haven't tried it, but it should work)

rpetrich
That works perfectly, thanks.
Kyle
A: 

Don't forget you can also use the CoreImage performance tool and get framerates if your drawRect is used often.

You could also use some of the performance tools to see how long is spent in that method.

Kendall Helmstetter Gelner