5

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

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

但这不会崩溃:

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

由 创建的路径是否有无效的地方makeToPath?一旦我解决了这个崩溃问题,我计划使用fromto路径。s fromCABasicAnimation的正确 ARC 桥接是什么?CGPathRefUIBezierPath

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

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

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

我还尝试让我的方法根据此处UIBezierPath的答案返回一个实例(如下所示)。仍然没有成功。有人想给我关于如何解决这个问题的详细解释吗?

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;
}
4

2 回答 2

8

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

在 .h 文件中:

-(CGPathRef)makeToPath CF_RETURNS_RETAINED;
-(CGPathRef)makeFromPath CF_RETURNS_RETAINED;
于 2013-01-22T19:35:24.497 回答
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);
}
于 2013-01-25T21:17:09.680 回答