对于不使用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对象?
答案 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
对象,它更具吸引力。