如何正确释放CF对象?

时间:2012-06-14 17:24:31

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

我有这种方法(别人写了!)

- (CGPDFDocumentRef)getPdf {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

    NSString *documentsDirectory = [paths objectAtIndex:0];

    NSString *pdfPath = [documentsDirectory stringByAppendingPathComponent:@"myLocalFileName.pdf"];

    NSURL *pdfURL = [NSURL fileURLWithPath:pdfPath];

    CGPDFDocumentRef pdf = CGPDFDocumentCreateWithURL((CFURLRef)pdfURL);

    return pdf;
}

现在,我运行了Analyze并获得了三个内存泄漏警告:

Call to function 'CGPDFDocumentCreateWithURL' returns a Core Foundation object with a +1 retain count
Object returned to caller as an owning reference (single retain count transferred to caller)
Object leaked: object allocated and stored into 'pdf' is returned from a method whose name ('getPdf') does not start with 'copy', 'mutableCopy', 'alloc' or 'new'.  This violates the naming convention rules given in the Memory Management Guide for Cocoa

有人可以告诉我这里需要/应该做些什么吗?我知道我应该在CF函数名称中创建或复制CFRelease所有内容。我不明白的是我如何发布pdf并仍能在函数结束时返回它。 我错过了什么? 谢谢。

4 个答案:

答案 0 :(得分:6)

您需要像http://cocoasamurai.blogspot.com/2012/01/clang-source-annotations.html

所示的clang源注释
    #import <AppKit/AppKit.h>
@interface NSColor (CWNSColorAdditions)
-(CGColorRef)cw_cgColor CF_RETURNS_RETAINED;
@end

答案 1 :(得分:5)

接收pdf的代码有责任在完成后将其发送给CFRelease。与Cocoa不同,CF不支持自动释放,因此从CF函数返回的任何对象都是调用者拥有且必须处理的对象。

返回CF对象的那些函数应该使用createcopy

进行相应的命名,这也是命名约定。

答案 2 :(得分:3)

由于您想要返回在函数中创建的对象,因此应正确命名函数本身以指示应该释放它返回的对象。

您可以调用您的函数getPdfcreatePdf,而不是copyPdf。这将告诉调用者它应该在完成时调用CFRelease,并且还满足Analyze的请求。

答案 3 :(得分:-1)

- (CGPDFDocumentRef)getPdf {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

    NSString *documentsDirectory = [paths objectAtIndex:0];

    NSString *pdfPath = [documentsDirectory stringByAppendingPathComponent:@"myLocalFileName.pdf"];

    NSURL *pdfURL = [NSURL fileURLWithPath:pdfPath];

    CGPDFDocumentRef pdf = CGPDFDocumentCreateWithURL((CFURLRef)pdfURL);

    return [pdf autorelease];
}

我认为这可以解决您的问题。