After updating my iPad (mini) to iOS7 I experienced that my drawing app is lagging and crashing after a few strokes.
Now, when I run the app with Instruments/memory allocation tool in xcode 5, I see that the VM: CG raster data category is filling up rapidly when drawing on the screen. There seems to be a multitude of CGDataProviderCreateWithCopyOfData calls being made, each 3.00Mb in size. After continous drawing the app receives memory warnings, and usually terminates.
The code basically strokes paths into an imagecontext, more or less like this:
UIGraphicsBeginImageContext(self.view.frame.size);
[drawImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 5.0);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 1.0, 0.0, 0.0, 1.0);
CGContextBeginPath(UIGraphicsGetCurrentContext());
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
On iOS7/iPad this is extremely laggy and has memory issues, while on iOS6 this was fairly speedy and had no negative memory footprint.
When I run this code in a non-retina iPhone version the CGDataProviderCreateWithCopyOfData calls are 604Kb in size, and only one or two are "active" at the same time. The drawing is fluent and fast with no memory warnings and no slowdown.
What happened from iOS6 to iOS7 regarding CoreGraphics and imagecontexts?
Sorry for any lingo errors or other possible stupid mistakes. Still a noob, doing iOS development in my spare time.
I put my drawing code in an autoreleasepool .and this solved my problem.
Eg:-
@autoreleasepool {
UIGraphicsBeginImageContext(self.view.frame.size);
[drawImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 5.0);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 1.0, 0.0, 0.0, 1.0);
CGContextBeginPath(UIGraphicsGetCurrentContext());
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
My solution in general was to create a Canvas UIView class that handles all drawing operations. I write to a cached CGImageRef and then combine the cache with the UIImage along the lines of this:
My custom drawRect method is something like this:
- (void)drawRect:(CGRect)rect
{
// Drawing code
UIGraphicsBeginImageContext(CGSizeMake(1024, 768));
CGContextRef context = UIGraphicsGetCurrentContext();
CGImageRef cacheImage = CGBitmapContextCreateImage(cacheContext);
CGContextDrawImage(context, self.bounds, cacheImage);
// Combine cache with image
drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
CGImageRelease(cacheImage);
UIGraphicsEndImageContext();
}
On touchesMoved I call a drawLine method that do some curve interpolation, brush size adjustment and end line tapering and then do a [self setNeedsDisplay];
This seems to be working well in iOS7. Sorry if I can't be more specific, but I'd rather not post actual production code from my app :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With