Quartz PDF API вызывает сбои из-за нехватки памяти

У меня возникают проблемы со сбоями при использовании Quartz PDF API для iOS. В настоящий момент я компилирую SDK 4.0 GM Seed и работаю на моем iPad 3.2 (я пробовал использовать SDK 3.2 с идентичными результатами).

Весь код, который я использую, основан на стандартной документации Apple Quartz и из различных источников в Интернете. Так что я не могу представить, что делаю что-то совершенно иное или неправильное.

Код отлично работает в Simulator (все версии, это универсальное приложение) и даже при использовании функции «Simulate Memory Warning». Я использовал инструмент «Утечки», и он не обнаружил никаких утечек. Build and Analyze тоже ничего не находит. В моей библиотеке не осталось журналов сбоев или нехватки памяти.

Все это наводит меня на мысль, что устройству не хватает памяти. Это происходит после просмотра, скажем, 50 страниц pdf, при этом около 35% имеют какое-то изображение (какая-то полная страница или какой-то значок). Он не вылетает ни на одной конкретной странице. PDF-файл, который я загружаю, составляет около 75 страниц и 3,5 МБ.

Я изучал похожие проблемы на этом сайте и в Интернете и применил некоторые советы из приведенного ниже кода. Теперь я публикую ссылку на документ pdf при каждом повороте страницы, и я больше не сохраняю / не отпускаю ссылку на страницу. Я также упростил замену изображений с использования CGImages на использование функции UIGraphicsGetImageFromCurrentImageContext. Я пробовал различные реализации для переключения изображений, включая полную замену pdfImgView только что выделенным временным экземпляром (с использованием [[UIImageView alloc] iniWithImage:UIGraphicsGetImageFromCurrentImageContext()]), используя установщик для pdfImgView и выпуская temp. Все варианты проходят тесты на утечки и анализатор, но по-прежнему демонстрируют то же поведение при сбое.

Итак, прежде чем я вообще откажусь от PDF-файлов, что я должен попробовать или чего-то мне не хватает?

Просмотрите код контроллера, который вызывается в обработчиках интерфейса для обмена страницами и при первой загрузке:

[self drawPage];

// ...animation code...simple CATransition animation...crashes with or without

// scrollView is a UIScrollView that is a subview of self.view
[scrollView.layer addAnimation:transition forKey:nil];
// pdfImgView is a UIImageView that is a subview of scrollView
pdfImgView.image = UIGraphicsGetImageFromCurrentImageContext();

Метод drawPage, используемый для настройки и отрисовки страницы PDF в контексте:

[CFURLRef pdfURL = CFBundleCopyResourceURL(CFBundleGetMainBundle(), CFSTR("BME_interior.pdf"), NULL, NULL);
pdfRef = CGPDFDocumentCreateWithURL((CFURLRef)pdfURL); // instance variable, not a property
CFRelease(pdfURL);
CGPDFPageRef page = CGPDFDocumentGetPage(pdfRef, currentPage);

CGRect box = CGPDFPageGetBoxRect(page, kCGPDFMediaBox);
// ...setting scale and imageHeight, both floats...

if (UIGraphicsBeginImageContextWithOptions != NULL) {
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(self.view.frame.size.width, imageHeight), NO, 0.0);
} else {
    UIGraphicsBeginImageContext(CGSizeMake(self.view.frame.size.width, imageHeight));
}
CGContextRef context = UIGraphicsGetCurrentContext();
NSLog(@"page is %d, context is %d, pdf doc is %d, pdf page is %d", currentPage, context, pdfRef, page); // all prints properly

// ...setting up scrollView for new page, using same instance...

CGContextTranslateCTM(context, (self.view.frame.size.width-(box.size.width*scale))/2.0f, imageHeight);
CGContextScaleCTM(context, scale, -1.0*scale);

CGContextSaveGState(context);
CGContextDrawPDFPage(context, page);
CGContextRestoreGState(context);

CGPDFDocumentRelease(pdfRef);
pdfRef = NULL;

person bensnider    schedule 21.06.2010    source источник
comment
Вы можете использовать инструменты, чтобы увидеть, какие объекты занимают всю доступную память. (Инструменты могут не только проверять утечки, но и проверять живые объекты.) Что это такое? Ответ будет зависеть от этого.   -  person Yuji    schedule 22.06.2010
comment
Мое оперативное выделение никогда не превышает ~ 12 МБ, и только потом внезапно увеличивается, а затем уменьшается, обычно выравнивается примерно на 3-5 МБ в режиме ожидания. Использование инструмента «Монитор памяти» сообщает мне, что объем виртуальной памяти моего приложения превышает 200 МБ, прежде чем он выйдет из строя. Я вижу предупреждения памяти уровня 1, затем уровня 2, а через несколько страниц произойдет сбой. Таким образом, изображения, кэшированные UIImage или UIImageView, если таковые имеются, должны быть выпущены, но очевидно, что что-то все еще существует.   -  person bensnider    schedule 22.06.2010


Ответы (2)


Ага! Я исправил сбои, добавив UIGraphicsEndImageContext(); перед началом нового контекста изображения. Я сейчас даже предупреждений о памяти не получаю ...

person bensnider    schedule 22.06.2010

Звонок

CGContextSetInterpolationQuality(context, kCGInterpolationHigh); 
CGContextSetRenderingIntent(context, kCGRenderingIntentDefault);

до того, как CGContextDrawPDFPage решил мою аналогичную проблему.

Кредиты относятся к этому ответу Иоганна: CGContextDrawPDFPage занимает большое количество память

person aslisabanci    schedule 11.08.2011