如何在需要返回CGImageRef时释放它?

5

我有一种方法可以调整CGImageRef的大小并返回CGImageRef。问题在于最后几行,我需要以某种方式释放它,但仍然需要返回它。有什么建议吗?谢谢

 -(CGImageRef)resizeImage:(CGImageRef *)anImage width:(CGFloat)width height:(CGFloat)height
{

    CGImageRef imageRef = *anImage;

    CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(imageRef);

    if (alphaInfo == kCGImageAlphaNone)
        alphaInfo = kCGImageAlphaNoneSkipLast;


    CGContextRef bitmap = CGBitmapContextCreate(NULL, width, height, CGImageGetBitsPerComponent(imageRef), 4 * width, CGImageGetColorSpace(imageRef), alphaInfo);

    CGContextDrawImage(bitmap, CGRectMake(0, 0, width, height), imageRef);

    CGImageRef ref = CGBitmapContextCreateImage(bitmap);

    CGContextRelease(bitmap);
    CGImageRelease(ref); //issue here

    return ref;

}

4
我认为在这种情况下,你应该将你的方法重命名为包含“new”或“copy”一词,然后简单地返回它而不释放它。调用者将从名称中了解到他们拥有对象并且负责释放它。 - borrrden
2个回答

7
Cocoa内存管理约定规定,若对象是通过以alloccopynew开头的方法创建,则你拥有该对象。
这些规则也被Clang静态分析器所遵守。
请注意,Core Foundation的约定略有不同。详细信息可以在苹果高级内存管理编程指南中找到。
我修改了您上面的方法以符合命名约定。我还删除了传入anImage时的星号,因为CGImageRef已经是一个指针。(或者这是故意的?) 请注意,你需要拥有返回的CGImage并稍后调用CGImageRelease
-(CGImageRef)newResizedImageWithImage:(CGImageRef)anImage width:(CGFloat)width height:(CGFloat)height
{
    CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(anImage);
    if (alphaInfo == kCGImageAlphaNone)
    {
        alphaInfo = kCGImageAlphaNoneSkipLast;
    }
    CGContextRef bitmap = CGBitmapContextCreate(NULL, width, height, CGImageGetBitsPerComponent(anImage), 4 * width, CGImageGetColorSpace(anImage), alphaInfo);
    CGContextDrawImage(bitmap, CGRectMake(0, 0, width, height), anImage);
    CGImageRef image = CGBitmapContextCreateImage(bitmap);
    CGContextRelease(bitmap);
    return image;
}

0

你也可以操作指针anImage(像@weichsel建议的那样去掉星号),并返回void

不过,你应该阅读你的代码并思考以下问题:

  • anImage是谁的所有权?(显然不是你的方法,因为它既没有保留也没有复制它)
  • 如果所有者在你的方法中释放它,会发生什么?(或者在你的代码运行时可能发生的其他事情)
  • 你的方法完成后它会发生什么?(即:你是否记得在调用代码中释放它)

因此,我强烈建议你不要混合使用CoreFoundation和Foundation。CoreFoundation使用函数、指针和“经典”数据结构,而Foundation使用对象和消息。

如果你想操作CF结构,你应该编写一个C函数来完成。如果你想操作Foundation对象,你应该编写(子)类和方法。如果你想混合两者或提供一个桥梁,你应该清楚自己在做什么,并编写包装器类来公开Foundation API并在内部处理所有CF内容(从而让你决定何时释放结构)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接