Khant Thu Linn Khant Thu Linn - 4 months ago 23
iOS Question

drawrect in very large uiview and memory is not sufficient

I am writing an app that user can draw on uiview. It works perfect if that uiview is in normal size (let say 1024 x 720). However, if I add that into uiscrollview and that dimension is 1024 x 3000, it become very slow. Also, if the height is 10000, the app crash on the spot. I would like to know how to do.

- (void) drawRect: (CGRect) rect
{
NSLog(@"drawrect here 1");

if (self.arrayStrokes)
{
int arraynum = 0;
// each iteration draw a stroke
// line segments within a single stroke (path) has the same color and line width
for (NSDictionary *dictStroke in self.arrayStrokes)
{
NSArray *arrayPointsInstroke = [dictStroke objectForKey:@"points"];
UIColor *color = [dictStroke objectForKey:@"color"];
float size = [[dictStroke objectForKey:@"size"] floatValue];
[color set]; // equivalent to both setFill and setStroke

// // won't draw a line which is too short
// if (arrayPointsInstroke.count < 3) {
// arraynum++;
// continue; // if continue is executed, the program jumps to the next dictStroke
// }

// draw the stroke, line by line, with rounded joints
UIBezierPath* pathLines = [UIBezierPath bezierPath];
CGPoint pointStart = CGPointFromString([arrayPointsInstroke objectAtIndex:0]);
[pathLines moveToPoint:pointStart];
for (int i = 0; i < (arrayPointsInstroke.count - 1); i++)
{
CGPoint pointNext = CGPointFromString([arrayPointsInstroke objectAtIndex:i+1]);
[pathLines addLineToPoint:pointNext];
}
pathLines.lineWidth = size;
pathLines.lineJoinStyle = kCGLineJoinRound;
pathLines.lineCapStyle = kCGLineCapRound;
[pathLines stroke];

arraynum++;
}
}
}

Rob Rob
Answer

There is nothing obvious in the code sample provided that would cause problem with really large views. I did a quick test and am drawing on a view that is 1024 x 10,000 without any incident. I ran a rendition of this through Instruments and the results were satisfyingly unexceptional:

Allocations

You should run your app through Instruments, and (a) make sure you have no leaks; and (b) look at the allocations and make sure it's level. If it's growing on you, you should identify what is causing that growth (by option-dragging in the allocations window or doing heapshots). Tons of issues can cause Allocations to grow (failure to CGRelease some Core Foundation object, mismatched begin/end of context, etc.), so I hesitate to guess what your issue might be. I don't see anything obvious in the code sample you've provided. I'd only suggest running your code through the static analyzer ("Analyze" on the "Product" menu) and see if it identifies anything.

Now, what can be problematic is saving this as a UIImage using renderInContext and UIGraphicsGetImageFromCurrentImageContext(). You haven't said you're doing that, but trying to create/save images will consume a startling amount of memory at those sizes.

If you're not familiar with using Instruments for tracking down memory issues, I'd suggest watching WWDC 2012 video iOS App Performance: Memory. It's a good primer on the topic.