在ARC下使用[UIBezierPath CGPath]和CAShapeLayer崩溃

时间:2013-01-22 19:19:00

标签: ios core-animation uibezierpath cashapelayer

我在ARC下使用[UIBezierPath CGPath]CAShapeLayer时出现了BAD ACCESS错误。我尝试过以各种方式进行桥接,但我不清楚这是不是问题。我已将崩溃隔离到使用makeToPath方法的结果:

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

但这不会崩溃:

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

makeToPath创建的路径是否有效?我计划使用{em>从和路径使用CABasicAnimation一次我将此崩溃排序。来自CGPathRef的{​​{1}}的正确ARC桥接是什么?

UIBezierPath

更新所以我根据下面的答案更改了我的.h文件,但我仍然遇到了崩溃

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

我还尝试让我的方法根据答案here返回-(CGPathRef)makeToPath CF_RETURNS_RETAINED; -(CGPathRef)makeFromPath CF_RETURNS_RETAINED; 个实例(如下所示)。仍然没有成功。有人想给我一些关于如何解决这个问题的长篇解释吗?

UIBezierPath

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

2 个答案:

答案 0 :(得分:8)

问题在于返回CGPath。返回的值是CGPathRef,ARC未涵盖该值。您创建的UIBezierPath将在方法结束后释放。因此也释放了CGPathRef。 您可以指定源注释以让ARC了解您的意图:

在.h文件中:

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

答案 1 :(得分:3)

正如另一张海报指出的那样,您将返回从UIBezierPath对象获取的CGPath引用,该对象超出了方法末尾的范围。由于UIBezierPath CGPath属性上的文档说:

  

路径对象本身由UIBezierPath对象拥有并且是   仅在您对路径进行进一步修改之前有效。

您需要创建CGPath的副本并返回:

-(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];
    CGPathRef theCGPath = [triangle CGPath];
    return CGPathCreateCopy(theCGPath);
}

我读取llvm项目链接的方式,我认为cf_returns_retained限定符旨在告诉调用者返回值的内存管理策略,而不是为你做保留。

因此我认为你们都需要创建路径的副本并添加cf_returns_retained限定符。但是,我不清楚该限定符的语法。 (从未使用过它。)

假设另一张海报有正确的语法,它看起来像这样:

-(CGPathRef)makeToPath CF_RETURNS_RETAINED;
{
    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];
    CGPathRef theCGPath = [triangle CGPath];
    return CGPathCreateCopy(theCGPath);
}