什么(tf)是PDF内存分配背后的秘密(CGPDFDocumentRef)

Kai*_*ann 7 memory pdf iphone ipad

对于PDF阅读器,我想通过拍摄每页的"屏幕截图"并将它们保存到光盘来准备文档.第一种方法是

CGPDFDocumentRef document = CGPDFDocumentCreateWithURL((CFURLRef) someURL);
for (int i = 1; i<=pageCount; i++) 
{
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];      
  CGPDFPageRef page = CGPDFDocumentGetPage(document, i);
  ...//getting + manipulating graphics context etc.
  ...
  CGContextDrawPDFPage(context, page);
  ...
  UIImage *resultingImage = UIGraphicsGetImageFromCurrentImageContext();
  ...//saving the image to disc 
  [pool drain];
}
CGPDFDocumentRelease(document);
Run Code Online (Sandbox Code Playgroud)

这导致在第一次循环运行(准备第一个文档)后似乎没有释放大量内存,但在其他运行中没有更多未释放的内存:

MEMORY BEFORE:          6 MB
MEMORY DURING 1ST DOC: 40 MB
MEMORY AFTER 1ST  DOC: 25 MB 
MEMORY DURING 2ND DOC: 40 MB
MEMORY AFTER 2ND  DOC: 25 MB
....
Run Code Online (Sandbox Code Playgroud)

将代码更改为

for (int i = 1; i<=pageCount; i++) 
{
  CGPDFDocumentRef document = CGPDFDocumentCreateWithURL((CFURLRef) someURL);
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];      
  CGPDFPageRef page = CGPDFDocumentGetPage(document, i);
  ...//getting + manipulating graphics context etc.
  ...
  CGContextDrawPDFPage(context, page);
  ...
  UIImage *resultingImage = UIGraphicsGetImageFromCurrentImageContext();
  ...//saving the image to disc 
  CGPDFDocumentRelease(document);
  [pool drain];
}
Run Code Online (Sandbox Code Playgroud)

将内存使用量更改为

MEMORY BEFORE:          6 MB
MEMORY DURING 1ST DOC:  9 MB
MEMORY AFTER 1ST  DOC:  7 MB 
MEMORY DURING 2ND DOC:  9 MB
MEMORY AFTER 2ND  DOC:  7 MB
....
Run Code Online (Sandbox Code Playgroud)

但显然是表现倒退了一步.

当我在第一种情况下开始阅读PDF(稍后时间,不同的线程)时,不再分配更多内存(保持25 MB),而在第二种情况下,内存最多可达20 MB(从7开始).

在这两种情况下,当我删除CGContextDrawPDFPage(context, page);行内存时,在所有文档准备期间和之后(几乎)常量为6 MB.

任何人都可以解释那里发生的事情吗?

omz*_*omz 4

CGPDFDocument 的缓存非常积极,除了像您所做的那样释放文档并从磁盘重新加载之外,您对此几乎没有控制权。

当您删除 CGContextDrawPDFPage 调用时看不到大量分配的原因是 Quartz 延迟加载页面资源。当您调用 CGPDFDocumentGetPage 时,所发生的只是加载一些基本元数据,例如边界框和注释(在内存中非常小)。

字体、图像等仅在您实际绘制页面时加载 - 但随后它们会在内部缓存中保留相对较长的时间。这是为了使渲染速度更快,因为页面资源通常在多个页面之间共享。此外,多次渲染页面(例如放大时)是相当常见的。您会注意到第二次渲染页面的速度要快得多。