属性的基础内存管理

时间:2014-03-24 13:59:12

标签: objective-c memory-management core-foundation

对于不使用ARC的项目,假设我的班级有一个属性:

@property (assign) CGPathRef pathRef;

我有一个方法在某个时候更新这个Path引用,例如:

UIBezierPath *bezierPath = [UIBezierPath bezierPathWithOvalInRect:rect];
self.pathRef = CGPathCreateCopy(bezierPath.CGPath);

在我的dealloc中,我的表现如下:

- (void)dealloc
{
    CGPathRelease(self.pathRef);
    self.pathRef = nil;

    [super dealloc];
}

运行静态分析器时,我正在获取我使用的行CGPathRelease的内存建议:

  

对象的引用计数的不正确减少   此时由来电者拥有。

我以为我在这里https://developer.apple.com/library/mac/qa/qa1565/_index.html,但似乎这解释了如何将基础对象交给核心动画API。

任何人都可以就此提出建议,如何在没有静态分析器警告的情况下管理此Foundation对象?

2 个答案:

答案 0 :(得分:3)

您不拥有属性访问者的返回值。改为使用实例变量。

CGPathRelease(_pathRef);

或者(最好),您可以自己实现访问器方法并包括内存管理。

- (void)setPathRef:(CGPathRef)val
{
    if (_pathRef)
    {
        CGPathRelease(_pathRef);
        _pathRef = NULL;
    }
    if (val)
    {
         _pathRef = CGPathCreateCopy(val);
    }
}

答案 1 :(得分:2)

此场景中另一个明显的解决方案是使用UIBezierPath对象,它可以让你摆脱CGPathRef创建/释放逻辑的杂草并绕过这个静态分析器特性。因此,定义一个属性:

@property (nonatomic, retain) UIBezierPath *bezierPath;

然后,当你想设置它时:

UIBezierPath *bezierPath = [UIBezierPath bezierPathWithOvalInRect:rect];
self.bezierPath = bezierPath;

当您需要CGPath时,只需从UIBezierPath抓取它,例如:

CGContextAddPath(context, self.bezierPath.CGPath);

然后在dealloc,你可以release

- (void)dealloc
{
    [_bezierPath release];
    [super dealloc];
}

这样,您可以享受对象内存语义的简单性,可以使用UIBezierPath的一些不错的便捷方法,可以使用其他不易用于Core Foundation类型的技术(例如autorelease),但是只要您需要它,您仍会获得CGPath

有时你必须采用Darren建议的技术之一(+1),特别是当没有一个与Core Foundation类型相对应的逻辑对象时,但在这个CGPathRef示例中,我通常使用UIBezierPath对象。鉴于您已经开始使用UIBezierPath对象,它更具吸引力。