iOS 7上的CoreGraphics绘图会导致内存警告/崩溃

10

iPad (mini) 升级到iOS7后,我的绘画应用程序在几笔之后开始出现延迟和崩溃。

现在,当我在 Xcode 5 中使用Instruments /内存分配工具运行该应用程序时,我发现CG光栅数据类别在屏幕上画图时迅速填满。似乎有大量的CGDataProviderCreateWithCopyOfData调用,每个大小为3.00Mb。连续绘制后,应用程序收到内存警告并通常终止。

该代码基本上会将路径涂抹到图像上下文中,差不多是这样的:

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();

在iOS7/iPad上,这个应用非常卡顿并且存在内存问题,而在iOS6上则相对流畅且没有负面的内存印记。

当我在非Retina iPhone版本中运行此代码时,CGDataProviderCreateWithCopyOfData调用大小为604Kb,同时只有一个或两个处于“活动”状态。绘图流畅快速,没有内存警告和减速现象。

iOS6和iOS7之间发生了什么关于CoreGraphics和imagecontexts的内容?

对于任何术语错误或其他可能的愚蠢错误,我表示抱歉。作为一名新手,我只是在业余时间进行iOS开发。


你好,你找到任何可能的解决方案了吗?我也遇到了同样的问题。 - Hubert Wang
还没有,但我正在研究将绘图代码移动到UIView的drawRect方法中(对于我的特定需求来说,这也有其它缺点)。如果我找到解决方案,我会发布更新。 - machineboy
ACEDrawingView是一个第三方库,在iOS7和iOS6中都有良好的性能。到目前为止,我还没有弄清楚我们的库与这个库之间的区别。也许你可以从中找到一些线索 +_+ - Hubert Wang
1
XCode 5 Instruments夸大了内存问题。当我使用Instruments时,我的应用程序会在30秒内崩溃,否则它运行良好,尽管在进行长时间连续的绘画过程中会使应用程序变慢(我也有一个放大镜或放大视图)。 - Gaurav Singh
嗨,我也遇到了同样的问题,你找到解决方案了吗?因为ARC也没有帮助到任何事情... - Rahul
2个回答

11

我将我的绘图代码放在了一个自动释放池中,这解决了我的问题。

例如:

@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();
}

哇,我在iPad Mini上也有这个问题,这个方法解决了这个问题!很奇怪,因为模拟器从来没有出现过这个问题。 - Solsma Dev

3

我的解决方案通常是创建一个Canvas UIView类来处理所有绘图操作。我写入缓存的CGImageRef,然后沿着这条线将缓存与UIImage组合:

我的自定义drawRect方法大致如下:

- (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();
}

在touchesMoved事件中,我调用了一个drawLine方法,该方法执行一些曲线插值、笔刷大小调整和线条收缩操作,然后调用[self setNeedsDisplay];

iOS7中似乎运行良好。很抱歉我无法提供更具体的信息,但我不想发布我的应用程序的实际生产代码 :)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接