Coregraphics(iOS)中的内存pipe理

我正在绘制应用程序,我正在使用CGlayers进行绘图,所以我打开canvas,点击一个button,

我使用的UIBezierPath,然后将其转换为CGPath在touchesMoved下面,然后使用它来绘制

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

我已经手动创build了setter方法

 -(void)setCurrentDrawingLayer:(CGLayerRef)layer { CGLayerRetain(layer); CGLayerRelease(currentDrawingLayer); currentDrawingLayer = layer; } 

现在,当用户点击保存button时,我通过这种方式从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]; } 

我得到的图像,并显示在屏幕上的网格与resize的图像,但是当我执行这些操作时,我的内存使用总是激增,而不是减less,这是创build三个图纸后的屏幕截图

要调整图像大小,我使用这个,我在一个单独的线程中运行

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

在这里输入图像说明

内存不断增加,最后创build了30个图纸后,我的应用程序崩溃,因为内存高达550MB

所以,我不明白我要去哪里错了,如何在绘图时pipe理内存问题。

你的mutablePath泄漏,因为你在-drawRect:释放了前一个-drawRect:并且只有当m_drawStep == DRAW )。 as -setNeedDisplay只是将视图标记为需要重绘。 -drawRect:只在下一个绘图周期发送,所以有几个-touchesMoved:withEvent:可以在两个绘图循环之间追加。 还有一些泄漏,当m_drawStep != DRAW时可能发生。

所以从-drawRect:方法中删除CGPathRelease(mutablePath) ,并在-touchesMoved:withEvent:释放它-touchesMoved:withEvent:

 CGPathRef cgPath = self.currentPath.path.CGPath; CGPathRelease(mutablePath); mutablePath = CGPathCreateMutableCopy(cgPath); [self setNeedsDisplay]; 

在设置CGLayerRef之后,还要释放您创build的-setCurrentDrawingLayer:因为您将其保存在-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... }