我正在开发一个绘图应用程序,我正在使用 CGlayers 进行绘图,所以我打开我的 Canvas 以通过单击按钮进行绘图,
我正在使用 UIBezierPath 然后在下面的 touchesMoved 中将它转换为 CGPath 然后用它来绘制
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
if (ctr == 4)
{
m_touchMoved = true;
self.currentPath = [[DrawingPath alloc] init];
[self.currentPath setPathColor:self.lineColor];
self.currentPath.pathWidth = [NSString stringWithFormat:@"%f",self.lineWidth];
pts[3] = midPoint(pts[2], pts[4]);// move the endpoint to the middle of the line joining the second control point of the first Bezier segment and the first control point of the second Bezier segment
[self.currentPath.path moveToPoint:pts[0]];
[self.currentPath.path addCurveToPoint:pts[3] controlPoint1:pts[1] controlPoint2:pts[2]];
CGPathRef cgPath = self.currentPath.path.CGPath;
mutablePath = CGPathCreateMutableCopy(cgPath);
[self setNeedsDisplay];
pts[0] = pts[3];
pts[1] = pts[4];
ctr = 1;
}
}
这是我的 drawRect 方法
- (void)drawRect:(CGRect)rect
{
switch (m_drawStep)
{
case DRAW:
{
CGContextRef context = UIGraphicsGetCurrentContext();//Get a reference to current context(The context to draw)
if(currentDrawingLayer == nil)
{
CGFloat scale = self.contentScaleFactor;
CGRect bounds = CGRectMake(0, 0, self.bounds.size.width * scale, self.bounds.size.height * scale);
CGLayerRef layer = CGLayerCreateWithContext(context, bounds.size, NULL);
CGContextRef layerContext = CGLayerGetContext(layer);
CGContextScaleCTM(layerContext, scale, scale);
//currentDrawingLayer = layer;
[self setCurrentDrawingLayer:layer];
CGLayerRelease(currentDrawingLayer);
}
CGContextRef layerContext = CGLayerGetContext(currentDrawingLayer);
CGContextBeginPath(layerContext);
CGContextAddPath(layerContext, mutablePath);
CGContextSetLineWidth(layerContext, self.lineWidth);
CGContextSetLineCap(layerContext, kCGLineCapRound);
CGContextSetLineJoin(layerContext, kCGLineJoinRound);
CGContextSetAllowsAntialiasing(layerContext, YES);
CGContextSetShouldAntialias(layerContext, YES);
CGContextSetStrokeColorWithColor(layerContext, self.lineColor.CGColor);
CGContextSetFillColorWithColor(layerContext, self.lineColor.CGColor);
CGContextSetBlendMode(layerContext,kCGBlendModeNormal);
CGContextStrokePath(layerContext);
CGPathRelease(mutablePath);
CGContextDrawLayerInRect(context, self.bounds, currentDrawingLayer );
}
break;
}
我已经手动创建了setter方法
-(void)setCurrentDrawingLayer:(CGLayerRef)layer
{
CGLayerRetain(layer);
CGLayerRelease(currentDrawingLayer);
currentDrawingLayer = layer;
}
现在当用户点击保存按钮时,我通过这种方式从 Canvas 中获取图像
-(void)getImageFromCanvas
{
UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO,0.0);//Creates a bitmap based graphics context with
//specified options
[self.layer renderInContext:UIGraphicsGetCurrentContext()];//Renders the reciever and its layers into specified
//context.
m_curImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();//Removes the current context from top of stack
if(currentDrawingLayer)
{
CGLayerRelease(currentDrawingLayer);
}
[m_delegate performSelectorOnMainThread:@selector(getCanVasViewImage:)
withObject:m_curImage
waitUntilDone:NO];
}
我得到图像并在屏幕上用调整大小的图像在网格上显示它,但是当我执行这些操作时,我的内存使用率总是飙升,而且没有减少,这是创建三张图后的屏幕截图
要调整图像大小,我使用它,我在单独的线程中运行它
dispatch_async(dispatch_get_global_queue(0,0), ^{
UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);
[image1 drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
});
内存不断增加,最后在创建了大约 30 张绘图后,我的应用程序崩溃了,因为内存达到 550MB
所以,我不明白我哪里出错了,我不知道如何在绘图时管理内存问题。
最佳答案
您的 mutablePath
泄漏,因为您在 -drawRect:
中释放了前一个(并且仅当 m_drawStep == DRAW
时)。因为 -setNeedDisplay
只是将 View 标记为需要重绘。
-drawRect:
仅在下一个绘图周期发送,因此多个 -touchesMoved:withEvent:
可能会在绘图周期之间附加。
还有一些泄漏,当 m_drawStep != DRAW
时可能发生。
所以从 -drawRect:
方法中移除 CGPathRelease(mutablePath)
并在 -touchesMoved:withEvent:
CGPathRef cgPath = self.currentPath.path.CGPath;
CGPathRelease(mutablePath);
mutablePath = CGPathCreateMutableCopy(cgPath);
[self setNeedsDisplay];
同时释放你在 -setCurrentDrawingLayer:
中设置后创建的 CGLayerRef
,因为你将它保留在 -setCurrentDrawingLayer:
中。
if(currentDrawingLayer == nil)
{
// ...
CGLayerRef layer = CGLayerCreateWithContext(context, bounds.size, NULL); // layer is created, refCount == 1
// ...
[self setCurrentDrawingLayer:layer]; // layer is retained by -setCurrentDrawingLayer:, refCount == 2
CGLayerRelease(layer); // release layer, refCount == 1
// without it the previous release layer refCount still == 2, so in -setCurrentDrawingLayer:
// CGLayerRelease(currentDrawingLayer) decrement refCount to 1 and leak...
}
关于ios - Coregraphics (iOS) 中的内存管理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22424743/