iOS 8.3 - CoreGraphics图像绘制中的EXC_BAD_ACCESS

时间:2015-04-27 12:06:37

标签: ios memory-management core-graphics cgcontext symbolicatecrash

在我的应用程序中,我有一个CoreGraphics图像绘制模块。应用程序在 CGContextAddPath()函数调用中随机崩溃。该路径是使用 CGPathCreateMutable()函数调用创建的 CGPathRef 对象。示例代码如下:

Private Sub UserForm_Initialize()

    Set Label1 = UserForm1.Controls.Add("Forms.Label.1", "Test", True)
    With Label1
        .Caption = "Test"
        .Left = 10
        .Width = 50
        .Top = 10
    End With

End Sub

从设备获取的诊断崩溃报告显示:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    if (touching) return;

    //start a new path
    path = CGPathCreateMutable();
    //set the path's starting point
    UITouch *touch = (UITouch *)[touches anyObject];
    CGPathMoveToPoint(path, NULL, [touch locationInView:m_view].x, [touch locationInView:m_view].y);

    touching = YES;
}

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    if (touching){
        //get the current location of the touch event
        UITouch *theTouch = (UITouch *)[touches anyObject];
        pathPoint = [theTouch locationInView:m_view];   
        CGPathAddLineToPoint(path, NULL, pathPoint.x, pathPoint.y);     
        [canvasLayer setNeedsDisplay];
    }
}

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    if (!touching) return;

    //create a new image context
    UIGraphicsBeginImageContext(CGSizeMake(backgroundLayer.bounds.size.width,  backgroundLayer.bounds.size.height));

    //grab a reference to the new image context
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    //push the image context to the top of the drawing stack
    UIGraphicsPushContext(ctx); 
    //set the blend mode to prevent white pixels from
    //covering up the lines that have already been drawn
    CGContextSetBlendMode(ctx, kCGBlendModeDarken);

    if (cacheImage != nil) {
        //draw the cached state of the image to the image context and release it
        [cacheImage drawInRect:CGRectMake(0, 0, backgroundLayer.bounds.size.width, backgroundLayer.bounds.size.height)];
    }

    //blend the drawing layer into the image context
    [canvasLayer drawInContext:ctx];
    //we're done drawing to the image context
    UIGraphicsPopContext();
    //store the image context so we can add to it again later
    cacheImage = UIGraphicsGetImageFromCurrentImageContext();

    //we're finished with the image context altogether
    UIGraphicsEndImageContext();
    touching = NO;
    //release the path
    CGPathRelease(path);

    //update the background layer (we'll need to draw the cached image to the background)
    [backgroundLayer setNeedsDisplay];
 }

- (void)drawLayer:(CATiledLayer *)layer inContext:(CGContextRef)ctx {
    //this method is handling multiple layers, so first
    //determine which layer we're drawing to
    if (layer == canvasLayer) {
        if (!touching) return;

        //add the path to the context
        CGContextAddPath(ctx, path); /***Exception points to this line***/
        //set a line width and draw the path
        CGContextSetLineWidth(ctx, 6.0f);//---thikness of line
        CGContextStrokePath(ctx);
    }
    else if (layer == backgroundLayer) {
        //remember the current state of the context
        CGContextSaveGState(ctx);
        //the cached image coordinate system is upside down, so do a backflip
        CGContextTranslateCTM(ctx, 0, backgroundLayer.bounds.size.height);
        CGContextScaleCTM(ctx, 1.0, -1.0);
        //draw the image
        CGImageRef ref = cacheImage.CGImage;
        CGContextDrawImage(ctx, backgroundLayer.bounds, ref);
        //restore the context to its pre-flipped state
        CGContextRestoreGState(ctx);
    }
}

当我在崩溃报告中表示内存地址时,异常指向 CGContextAddPath(ctx,path); 。是否是使用 CGPathRelease(path); 显式释放路径引起的?如果我注释掉释放功能,应用程序不会崩溃,但会引入内存泄漏吗?

1 个答案:

答案 0 :(得分:1)

你破坏touchEnded中的路径,但之后可能会调用drawLayer。