Ios – Crash using [UIBezierPath CGPath] with CAShapeLayer under ARC

cashapelayercore-animationiosuibezierpath

I'm getting a BAD ACCESS error using [UIBezierPath CGPath] with CAShapeLayer under ARC. I've tried bridging in various ways but I'm not clear if that is the problem. I have isolated the crash to using the result of the makeToPath method:

 maskLayer = [CAShapeLayer layer];
 maskLayer.path = [self makeToPath];

But this doesn't crash:

 maskLayer = [CAShapeLayer layer];
 maskLayer.path = [self makeFromPath];

Is there something invalid with the path created by makeToPath? I'm planning to use the from and to paths with a CABasicAnimation once I sort this crash out. What is the correct ARC bridging for CGPathRefs from UIBezierPath?

-(CGPathRef)makeToPath
{
    UIBezierPath* triangle = [UIBezierPath bezierPath];
    [triangle moveToPoint:CGPointZero];
    [triangle addLineToPoint:CGPointMake(self.view.frame.size.width,0)];
    [triangle addLineToPoint:CGPointMake(0, self.view.frame.size.height)];
    [triangle closePath];
    return [triangle CGPath];
}

-(CGPathRef)makeFromPath
{
    UIBezierPath*rect = [UIBezierPath bezierPathWithRect:self.view.frame];
    return [rect CGPath];
}

UPDATE So I changed my .h file per an answer below but I am still getting the crash

-(CGPathRef)makeToPath CF_RETURNS_RETAINED;
-(CGPathRef)makeFromPath CF_RETURNS_RETAINED;

I also tried making my methods return a UIBezierPath instance per the answer here (shown below). Still no success. Anyone want to give me the longform explanation on how to fix this?

maskLayer.path = [[self makeToPath] CGPath];// CRASHES
morph.toValue =  CFBridgingRelease([[self makeToPath] CGPath]);// CRASHES

-(UIBezierPath*)makeToPath
{
    UIBezierPath* triangle = [UIBezierPath bezierPath];
    [triangle moveToPoint:CGPointZero];
    [triangle addLineToPoint:CGPointMake(self.view.frame.size.width,0)];
    [triangle addLineToPoint:CGPointMake(0, self.view.frame.size.height)];
    [triangle closePath];
    return triangle;
}

Best Answer

The problem is with returning the CGPath. The value returned is a CGPathRef which is not covered by ARC. The UIBezierPath you create is released after the method ends. Thus also freeing the CGPathRef. You can specify a source annotation to let ARC know your intent:

In the .h file:

-(CGPathRef)makeToPath CF_RETURNS_RETAINED;
-(CGPathRef)makeFromPath CF_RETURNS_RETAINED;
Related Topic