Как выгрузить изображения iPhone, чтобы освободить память - PullRequest
1 голос
/ 01 июня 2011

У меня есть игра для 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, либо при выгрузке, либо при загрузке во второй раз (т.е. когда это необходимо снова). Я не вижу ничего другого, что помогло бы определить истинную причину проблемы.

Возможно, я атакую ​​эту проблему с неправильной точки зрения. Каков обычный метод отложенной загрузки изображений и как обычно выгрузить изображение, чтобы освободить память?

Заранее большое спасибо,

Sam

1 Ответ

1 голос
/ 01 июня 2011

Вам следует избегать использования метода [UIImage imageNamed: name] любой ценой, если вы хотите, чтобы вещи не оставались в кэше.imageNamed кэширует все изображения, через которые проходит.Вы хотите использовать

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

При этом вы можете просто освободить объект, когда закончите с ним, и освободить память.

Apple улучшила кэширование с помощью [UIImage imageNamed:], ноэто все еще не по требованию.

...