我在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
答案 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);
}