无法使用 400+ 创建 PDF 文档iOS 上的页面

发布于 2024-11-05 02:53:40 字数 527 浏览 4 评论 0原文

我正在使用以下伪代码生成 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 页(收到的 崩溃之前有两个内存警告。)我已经使用以下命令确保没有泄漏 仪器仪表。您对在 iOS 上创建大型 PDF 文档有何建议?多谢。

编辑:pdf 创建是在后台线程中完成的。

I am using the following pseudocode to generate a PDF document:

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);

It works very well with small documents (N < 100 pages), but it uses too much
memory and crashes if the document has more than about 400 pages (it received
two memory warnings before crashing.) I have made sure there were no leaks using
Instruments. What's your advice on creating large PDF documents on iOS? Thanks a lot.

edit: The pdf creation is done in a background thread.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

寒江雪… 2024-11-12 02:53:40

由于您是通过 CGPDFContextCreateWithURL 创建单个文档,因此整个内容必须保存在内存中并附加到通常的内容(尽管我不能肯定 iOS 和 CGPDFContextCreateWithURL< /code>)需要保留文档的完整之前之后副本。即使没有前后问题,也不需要泄漏来产生问题。

如果您不想捕获一堆现有的 UIKit 绘制的东西(在您的示例中似乎您没有这样做),请改用操作系统的打印方法,它提供 内置支持打印为 PDFUIGraphicsBeginPDFContextToFile 在添加页面时将其写入磁盘,因此整个内容不必立即保存在内存中。这样你应该能够生成一个巨大的 PDF。

Since you're creating a single document via CGPDFContextCreateWithURL the entire thing has to be held in memory and appended to, something that commonly (though I can't say for certain with iOS and CGPDFContextCreateWithURL) requires a full before and after copy of the document to be kept. No need for a leak to create a problem, even without the before-and-after issue.

If you aren't trying to capture a bunch of existing UIKit-drawn stuff -- and in your sample it seems that you're not -- use the OS's printing methods instead, which offer built-in support for printing to a PDF. UIGraphicsBeginPDFContextToFile writes the pages out to disk as they're added so the whole thing doesn't have to be held in memory at once. You should be able to generate a huge PDF that way.

独行侠 2024-11-12 02:53:40

或许这不是你想听到的答案,但从另一个角度来看。

您是否可以将其视为设备的限制?...首先检查PDF中的页数,如果太大,则向用户发出警告。因此要优雅地处理它。

然后您可以对此进行扩展...

您可以在 iDevice 上构建小型 PDF,如果 PDF 太大,则在下次 iDevice 有网络连接时在服务器端构建它。

Probably not the answer you want to hear, but looking at it from another perspective.

Could you consider it as a limitation of the device?... First check the number of pages in the PDF and if it is too large, give a warning to the user. Therefore handling it gracefully.

You could then expand on this....

You could construct small PDF's on the iDevice and if the PDF is too large, construct it server-side the next time the iDevice has a net connection.

千里故人稀 2024-11-12 02:53:40

如果分配太多内存,您的应用程序将会崩溃。为什么生成异常大的 PDF 是一个目标?你到底想实现什么目标?

If you allocate too much memory, your app will crash. Why is generating an unusually large PDF a goal? What are you actually trying to accomplish?

∞觅青森が 2024-11-12 02:53:40

使用内存映射文件来支持 CG 数据消费者怎么样?那么它不一定需要一次性全部装入 RAM。

我在这里创建了一个示例: 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;

What about using a memory mapped file to back your CG data consumer? Then it doesn't necessarily have to fit in RAM all at once.

I created an example here: https://gist.github.com/3748250

Use it like this:

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文