Освобождение результата renderInContext в цикле - PullRequest
7 голосов
/ 11 февраля 2011

У меня есть метод, который вызывается в цикле, который выглядит примерно так:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
UIImageView *background = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, PAGE_WIDTH, PAGE_HEIGHT)];
background.image = backgroundImg;

for (UIView *view in viewArray)
{
    [background addSubview:view];
}

UIGraphicsBeginImageContext(background.frame.size);
[background.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

for (UIView *view in background.subviews)
    [view removeFromSuperview];

background.image = nil;
[background release];
[image retain];
[pool drain];
[image autorelease];
return image;

Однако, в соответствии с Instruments Memory Monitor, использование памяти увеличивается и увеличивается и никогда не снижается до конца цикла. (Вылетает.)

Если я заменю UIGraphicsBeginImageContext на UIGraphicsEndImageContext на

UIImage * image = someotherimage;

тогда память не скачет, а будет выделяться и уменьшаться на каждой итерации цикла, как я и ожидал, из-за пула автоматического выпуска. (Не падает)

И если я просто закомментирую строку renderInContext, она будет работать нормально. (Не вылетает)

Итак, похоже, что renderInContext каким-то образом удерживает изображение - как я могу заставить его выпустить его? Или любые альтернативные предложения, пожалуйста:)?

Ответы [ 2 ]

15 голосов
/ 11 февраля 2011

Естественно, после 3 дней экспериментов я нахожу ответ (в любом случае ответ, и я был бы рад комментариям по этому поводу) в течение часа.

Я добавляю

background.layer.contents = nil;

после

UIGraphicsEndImageContext();

и кэшированная память в слое не кэшируется:).

0 голосов
/ 11 апреля 2017

Я не использую UIImageView, поэтому настройка layer.contents = nil у меня не сработала.Однако я нашел другое решение, которое, хотя и не идеально, работает.Похоже, что память, выделенная renderInContext, не освобождается, пока main_queue не находится в режиме ожидания.Итак, я сделал следующее:

dispatch_queue_t queue = dispatch_queue_create("com.example.imageprocessing", DISPATCH_QUEUE_SERIAL);

for (int k = 0; k < images.count; ++k) {
    dispatch_async(queue, ^{
        dispatch_sync(dispatch_get_main_queue(), ^{
            @autoreleasepool {
                ...
                UIGraphicsBeginImageContext(self.view.bounds.size);
                [view.layer renderInContext:UIGraphicsGetCurrentContext()];
                image = UIGraphicsGetImageFromCurrentImageContext();
                UIGraphicsEndImageContext();
                ...
            }
        }
    }
}

Это решило мою проблему с памятью.Я не обрабатываю много изображений, поэтому не знаю, как это влияет на производительность.

...