Reputation: 6177
In my app, I have to draw some images on a view, in real-time, in positions and scaling that frequently change over time. These images are a subset of those contained in a dictionary. Here is the code, a bit summarized:
-(void)drawObjects:(NSArray*)objects withImages:(NSDictionary*)images <etc>
{
// Get graphic context and save it
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
// Display objects in reverse order
for (int i = [objects count] - 1; i >= 0; i--) {
MyObject *object = [objects objectAtIndex:i];
// Check if object shall be visible
if (<test to check whether the image shall be visible or not>) {
// Get object image
UIImage* image = <retrieve image from "images", based on a key stored in "object">;
// Draw image
float x = <calculate image destination x>;
float y = <calculate image destination y>;
float imageWidth = <calculate image destination width>;
float imageHeight = <calculate image destination height>;
CGRect imageRect = CGRectMake(x - imageWidth / 2, y - imageHeight / 2, imageWidth, imageHeight);
[image drawInRect:imageRect];
}
}
// Restore graphic context
CGContextRestoreGState(context);
}
My problem is that this code is slow; it takes about 700 to 800 ms to perform the loop, when the number of images is about 15 (iPhone 4, iOS 4.3.5). I have experimented a bit, and it seems that the bottleneck is the drawInRect call, since if I exclude it, everything speeds up drammatically.
Does anyone have suggestions to offer?
Upvotes: 2
Views: 5978
Reputation: 9902
The problem is (I think) that you are actually drawing (creating the screen representation) the image in every frame, because drawInRect:
has no idea that you want to reuse the image that you displayed in the last frame. But you don't need that. You only want to draw it once, and then transform it afterwards to change its position and size.
UIKit makes this easy for you: Just set the frame for a UIImageView
, and the image will be displayed where and how large you want it, without needing to re-render the image data.
You can probably optimize this further by storing the UIImageViews themselves, so that they don't have to be recreated every time they need to be displayed. Istead just set their hidden
property accordingly.
Upvotes: 2
Reputation: 8339
Your number one answer: run Instruments and see what part of this is actually taking time. (Yes, chances are it's the drawInRect: but it could be the "get the image" you didn't show).
Upvotes: 0