views:

354

answers:

1

Hey guys,

So I'm trying to make a UITableView that has a repeating background. I want the background to scroll with the text. The catch is that the background is 2 images. There is a top image that is about 550px in height, and then a repeater image that's 2px in height. I want the top image to scroll with the table view and then eventually go off the top and then the segment image just repeats. This view actually sits below a UITableView in a view controller.

Here's my drawrect for the background. I call setNeedsDisplay when ever the tableview on top scrolls.

-(void)drawRect:(CGRect) rect 
{

    CGRect topRect = CGRectMake(0, _tableViewRect.origin.y, 320, min( max(0, CGImageGetHeight(top) - _tableViewRect.origin.y), _tableViewRect.size.height));
    CGRect segmentRect = CGRectMake(0, topRect.size.height, 320, _tableViewRect.size.height - topRect.size.height);

    if(topRect.size.height > 0)
    {
        CGImageRef newImageRef = CGImageCreateWithImageInRect(top, topRect);  
        UIImage *newImage = [UIImage imageWithCGImage:newImageRef];  
        [newImage drawAtPoint:CGPointMake(0,0)];
    }

    [[UIImage imageWithCGImage: segment] drawAsPatternInRect:segmentRect];
}

It works but it is very chuggy on my 3G. Does anyone have any optimization tips, or another way of doing this?

Cheers

+2  A: 

Don't create a new image each time; cache your UIImage, then use CoreGraphics calls to reposition your CGContextRef to 'point' to the right area, blit the image there, and move on. If you were to profile the code above, I imagine that CGImageCreateWithImageInRect() was taking up the vast majority of your cycles.

You should probably do this using contentOffset, rather than whatever _tableViewRect is. Also, looking at your code, while getting rid of the stuff above will help, I'm not sure it'll be enough, since you'll be redrawing a LOT. That said, here's a snippet that may work:

//I'm not sure what _tableViewRect is, so let's just assume you've got
//some variable, tableScrollY, that represents the scroll offset of your table

CGContextRef      context = UIGraphicsGetCurrentContext();

if (tableScrollY < top.size.height) {      //okay, we need to draw at least PART of our image
    CGContextSaveGState(context);
    CGContextDrawImage(context, CGRectMake(0, -tableScrollY, top.size.width, top.size.height), top.CGImage);
 }

This should be a replacement for the middle if(...) portion of your code. This is not tested, so you may need to futz with it a bit.

Ben Gottlieb
Oh okay. What's the best way to blit. That's what I wanted to do but couldn't really find anything.
Meroon
Check out the CGContextRef docs (http://developer.apple.com/mac/library/DOCUMENTATION/GraphicsImaging/Reference/CGContext/Reference/reference.html), specifically CGContextDrawImage. Remember, you can get a CGImageRef out of a UIImage using the .CGImageRef property.
Ben Gottlieb
I'm having trouble figuring out how to properly blit. Can you direct me to any articles that discuss this? Or do you have any code? I really appreciate your help.
Meroon
Is there any way to turn scaling off with CGContextDrawImage? I'd be golden if it didn't scale the image.
Meroon
You'll want to look at affine transformations, and, specifically, CGContextScaleCTM().
Ben Gottlieb