【问题标题】:How to release CGImageRef if required to return it?如果需要返回它,如何释放 CGImageRef?
【发布时间】:2013-06-10 02:46:17
【问题描述】:

我有一种方法可以调整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;

}

【问题讨论】:

  • 我相信在这种情况下你应该重命名你的方法以包含单词“new”或“copy”,然后简单地返回它而不释放。调用者会从名字中明白他们拥有该对象并负责释放它。

标签: ios macos cocoa core-graphics


【解决方案1】:

Cocoa 内存管理命名策略规定,您拥有一个由名称以 alloccopynew开头的方法创建的对象>.
Clang 静态分析器也遵守此规则。

请注意,Core Foundation 的约定略有不同。详情请见Apple's Advanced Memory Management Programming Guide

我修改了您的上述方法以符合该命名约定。在传入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;
}

【讨论】:

    【解决方案2】:

    您还可以对指针anImage 进行操作(在删除星号后,如@weichsel 建议的那样)并返回void

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

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

    因此,我强烈建议您不要将 CoreFoundation 与函数、指针和“经典”数据结构一起使用,而 Foundation 与对象和消息一起使用。 如果你想对 CF 结构进行操作,你应该编写一个 C 函数来完成它。如果你想对基础对象进行操作,你应该编写带有方法的(子)类。如果你想混合两者或提供一个桥梁,你应该确切地知道你在做什么,并编写暴露基础 API 并在内部处理所有 CF 内容的包装类(因此何时发布结构留给你)。

    【讨论】:

      猜你喜欢
      • 2010-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-06
      • 2010-12-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多