Невозможно создать PDF документ с 400+ страницами на iOS - PullRequest
16 голосов
/ 04 мая 2011

Я использую следующий псевдокод для создания документа PDF:

CGContextRef context = CGPDFContextCreateWithURL(url, &rect, NULL);

for (int i = 1; i <= N; i++)
{
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  CGContextBeginPage(context, &mediaBox);

  // drawing code

  CGContextEndPage(context);
  [pool release];
}

CGContextRelease(context);

Очень хорошо работает с небольшими документами (N < 100 страницы), но использует слишком много памяти и вылетает, если документ имеет более 400 страниц (он получил два предупреждения памяти перед сбоем.) Я удостоверился, что не было никаких утечек, используя Инструменты. Что вы посоветуете при создании больших PDF-документов на iOS? Большое спасибо.

edit: создание pdf выполняется в фоновом потоке.

Ответы [ 4 ]

6 голосов
/ 04 мая 2011

Поскольку вы создаете один документ с помощью CGPDFContextCreateWithURL, все это нужно хранить в памяти и добавлять к нему, что обычно (хотя я не могу сказать наверняка с iOS и CGPDFContextCreateWithURL) требует полного до и после копия документа, который необходимо сохранить. Нет необходимости в утечке, чтобы создать проблему, даже без проблемы до и после.

Если вы не пытаетесь захватить кучу существующих UIKit-нарисованных вещей - а в вашем примере кажется, что это не так - используйте вместо этого методы печати ОС, которые предлагают встроенный -в поддержке печати в PDF . UIGraphicsBeginPDFContextToFile записывает страницы на диск по мере их добавления, поэтому все это не нужно хранить в памяти сразу. Таким образом вы сможете создать огромный PDF-файл.

3 голосов
/ 12 мая 2011

Возможно, это не тот ответ, который вы хотите услышать, но если посмотреть на него с другой стороны.

Не могли бы вы считать это ограничением устройства? ... Сначала проверьте количество страниц в PDF иесли он слишком большой, предупредите пользователя.Поэтому обрабатывайте его изящно.

Затем вы можете расширить это ....

Вы можете создать небольшие PDF-файлы на iDevice, а если PDF слишком большой, создайте его на стороне сервера следующимвремя у iDevice есть сетевое соединение.

1 голос
/ 19 сентября 2012

Как насчет использования файла с отображенной памятью для поддержки вашего потребителя данных CG? Тогда он не обязательно должен помещаться в ОЗУ одновременно.

Я создал пример здесь: https://gist.github.com/3748250

Используйте это так:

NSURL * url = [ NSURL fileURLWithPath:@"pdf.pdf"] ;
MemoryMappedDataConsumer * consumer = [ [ MemoryMappedDataConsumer alloc ] initWithURL:url ] ;

CGDataConsumerRef cgDataConsumer = [ consumer CGDataConsumer ] ;

CGContextRef c = CGPDFContextCreate( cgDataConsumer, NULL, NULL ) ;
CGDataConsumerRelease( cgDataConsumer ) ;

// write your PDF to context `c`

CGPDFContextClose( c ) ;
CGContextRelease( c ) ;

return 0;
1 голос
/ 04 мая 2011

Если вы выделите слишком много памяти, ваше приложение будет зависать.Почему создание необычно большого PDF-файла является целью?Чего вы на самом деле пытаетесь достичь?

...