通过 Coregraphic 画线:renderInContext 崩溃

B2G*_*h T 5 iphone core-graphics objective-c ios12 xcode10

我正在使用 CoreGraphics 画一条线。我刚刚更新了 Xcode 10 和 iOS 12。在 iOS 12 中,我的应用程序崩溃了。尽管如此,它在 iOS 11.4.1 和之前的版本中仍然运行良好。我无法解决这个问题。请在下面找到我的代码

-(void)drawRect:(CGRect)rect
{
    CGPoint mid1 = midPoint(previousPoint1, previousPoint2); 
    CGPoint mid2 = midPoint(currentPoint, previousPoint1);

    CGContextRef context = UIGraphicsGetCurrentContext(); 

    [self.layer renderInContext:context];

    CGContextMoveToPoint(context, mid1.x, mid1.y);
    CGContextAddQuadCurveToPoint(context, previousPoint1.x, previousPoint1.y, mid2.x, mid2.y); 
    CGContextSetLineCap(context, kCGLineCapRound);
    CGContextSetLineWidth(context, self.lineWidth);
    CGContextSetStrokeColorWithColor(context, self.lineColor.CGColor);

    CGContextSetShadow(context, CGSizeMake(-16.00, -5.0f), 5.0f);

    CGContextStrokePath(context);

    [super drawRect:rect];
    [curImage release];
} 
Run Code Online (Sandbox Code Playgroud)

下面是touchesMoved方法。

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{

    UITouch *touch  = [touches anyObject];

    previousPoint2  = previousPoint1;
    previousPoint1  = [touch previousLocationInView:self];
    currentPoint    = [touch locationInView:self];

    // calculate mid point
    CGPoint mid1    = midPoint(previousPoint1, previousPoint2); 
    CGPoint mid2    = midPoint(currentPoint, previousPoint1);

    CGMutablePathRef path = CGPathCreateMutable();
    CGPathMoveToPoint(path, NULL, mid1.x, mid1.y);
    CGPathAddQuadCurveToPoint(path, NULL, previousPoint1.x, previousPoint1.y, mid2.x, mid2.y);
    CGRect bounds = CGPathGetBoundingBox(path);
    CGPathRelease(path);

    CGRect drawBox = bounds;

    //Pad our values so the bounding box respects our line width
    drawBox.origin.x        -= self.lineWidth * 2;
    drawBox.origin.y        -= self.lineWidth * 2;
    drawBox.size.width      += self.lineWidth * 4;
    drawBox.size.height     += self.lineWidth * 4;

    UIGraphicsBeginImageContext(drawBox.size);
    [self.layer renderInContext:UIGraphicsGetCurrentContext()];
    curImage = UIGraphicsGetImageFromCurrentImageContext();
    [curImage retain];
    UIGraphicsEndImageContext();
   [self setNeedsDisplayInRect:drawBox];

}

CGPoint midPoint(CGPoint p1, CGPoint p2)
{
    return CGPointMake((p1.x + p2.x) * 0.5, (p1.y + p2.y) * 0.5);
}


-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{

    UITouch *touch = [touches anyObject];

    previousPoint1 = [touch previousLocationInView:self];
    previousPoint2 = [touch previousLocationInView:self];
    currentPoint = [touch locationInView:self];

    [self touchesMoved:touches withEvent:event];
}
Run Code Online (Sandbox Code Playgroud)

问题是在代码崩溃[self.layer renderInContext:context];(void)drawRect:(CGRect)rect功能。drawRect 函数被调用太多时间(大约 5000 次)和内存过载(大约 20Gb)导致应用程序崩溃。iOS 12 和 Xcode 10 会有变化吗?

我修复了这个问题。更新我的新 toucheMoved() 函数:

- (void) touchesMoved: (NSSet*) touches withEvent: (UIEvent*) event
{    
previousPoint2 = previousPoint;
previousPoint = [touch previousLocationInView:self];
location = [touch locationInView:self];

CGPoint mid1 = midPoint(previousPoint, previousPoint2);
CGPoint mid2 = midPoint(location, previousPoint);

CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, mid1.x, mid1.y);
CGPathAddQuadCurveToPoint(path, NULL, previousPoint.x, previousPoint.y, mid2.x, mid2.y);
CGRect bounds = CGPathGetBoundingBox(path);
CGPathRelease(path);

CGRect drawBox = bounds;

drawBox.origin.x -= self.lineWidth * 2;
drawBox.origin.y -= self.lineWidth * 2;
drawBox.size.width += self.lineWidth * 4;
drawBox.size.height += self.lineWidth * 4;

UIGraphicsBeginImageContextWithOptions(totalDrawBox.size, self.opaque, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGAffineTransform affineMoveLeftTop = CGAffineTransformMakeTranslation(-(int)totalDrawBox.origin.x, -(int)totalDrawBox.origin.y);
CGContextConcatCTM(context, affineMoveLeftTop);
float iOSVersion = [[UIDevice currentDevice].systemVersion floatValue];
if (iOSVersion >= 12) {
    [self setNeedsDisplay];
} else {
    [self.layer renderInContext: context];
}
curImage = UIGraphicsGetImageFromCurrentImageContext();
CGContextStrokePath(context);
UIGraphicsEndImageContext();
}
Run Code Online (Sandbox Code Playgroud)

sar*_*pol 3

我的工作是

不要让layer renderInContext在drawRect中递归调用

(我的代码很快)

var mIsInDrawLoop = false

// -(void)drawRect:(CGRect)rect
override func draw(_ rect: CGRect) {
...
    if(!mIsInDrawLoop) {
        mIsInDrawLoop = true
        layer.render(in: context)
        // [self.layer renderInContext:context];
        mIsInDrawLoop = false
    }
...
}
Run Code Online (Sandbox Code Playgroud)