如何卸载iPhone图像以释放内存

时间:2011-06-01 14:24:13

标签: iphone image memory-management cgimageref

我有一款iPhone游戏,它使用图像显示屏幕上的按钮等内容来控制游戏。图像并不大,但我想“懒洋洋地”加载它们,并在不使用时从内存中卸载它们。

我有一个加载图像的功能如下:

void loadImageRef(NSString *name, GLuint location, CGImageRef *textureImage)
{
    *textureImage = [UIImage imageNamed:name].CGImage;

    if (*textureImage == nil) {
        NSLog(@"Failed to load texture image");
        return;
    }

    NSInteger texWidth = CGImageGetWidth(*textureImage);
    NSInteger texHeight = CGImageGetHeight(*textureImage);

    GLubyte *textureData = (GLubyte *)malloc(texWidth * texHeight * 4);

    CGContextRef textureContext = CGBitmapContextCreate(textureData,
                                                        texWidth, texHeight,
                                                        8, texWidth * 4,
                                                        CGImageGetColorSpace(*textureImage),
                                                        kCGImageAlphaPremultipliedLast);

    CGContextTranslateCTM(textureContext, 0, texHeight);
    CGContextScaleCTM(textureContext, 1.0, -1.0);

    CGContextDrawImage(textureContext, CGRectMake(0.0, 0.0, (float)texWidth, (float)texHeight), *textureImage);
    CGContextRelease(textureContext);

    glBindTexture(GL_TEXTURE_2D, location);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData);

    free(textureData);

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}

我将CGImageRef传递给函数的原因是我以后可以释放它。但我不知道这是否是正确的做法?

我按如下方式调用该函数(例如):

loadImageRef(@"buttonConfig.png", textures[IMG_CONFIG], &imagesRef[IMG_CONFIG]);

当我完成它时,我按如下方式卸载它:

unloadImage(&imagesRef[IMG_CONFIG]);

调用函数:

void unloadImage(CGImageRef *image)
{
    CGImageRelease(*image);
}

但是当我运行应用程序时,无论是卸载还是第二次加载(即再次需要时),都会出现EXC_BAD_ACCESS错误。我没有看到任何其他东西来帮助确定问题的真正原因。

也许我从错误的角度攻击这个问题。什么是延迟加载图像的常用方法,以及卸载图像以释放内存的常用方法是什么?

非常感谢,

萨姆

1 个答案:

答案 0 :(得分:1)

如果要确保不缓存内容,则应该不惜一切代价避免使用[UIImage imageNamed:name]方法。 imageNamed缓存它所经过的所有图像。你想用

UIImage *image = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:fileNameWithoutExtension ofType:fileNameExtension]];

有了它,您可以在完成后释放该对象并释放内存。

Apple使用[UIImage imageNamed:]改进了缓存,但仍然没有按需提供。