如何在iOS上的PDF中检索大纲目的地的页码或页面参考?

我一直在阅读Adobe PDF规范,以及苹果石英二维文档的PDF渲染和parsing。 我也下载了偷窥者,并检查了一下本地的pdf,看看它的内部数据。 在这一点上,我能够获得文档目录,然后从那里获取轮廓词典。 我可以看到,嵌套在大纲词典字典中,名为“/ Dest”的节点的值如下:

G1.1025588等

我想知道是否有一种方法让我使用这些值来获取页面的引用使用一些方法,我已经看到github项目,如读者,以及苹果logging的例子。

PDF处理绝对是一个挑战,所以任何帮助将不胜感激。

大纲项目字典中的/Dest项可以是名称string数组

  • 最简单的情况是如果它是一个数组 ; 那么第一个项目就是大纲条目所指向的页面对象(一个字典)。 为了得到页码,你必须迭代文档中的所有页面,看看哪一个与你所拥有的字典( == )相等( CGPDFDictionaryRef实际上是CGPDFDictionaryRef )。 你也可以遍历页面树,这有点困难,但可能会更快(没有你期望的那么多,我不会在这里过早优化)。 数组中的其他项目位于页面上,在PDF规范中search“显式目的地”以了解更多信息。

  • 如果条目是名称string ,则它是一个指定的目的地。 您必须将名称映射到文档目录的/Dests条目中,该条目是包含名称树的字典。 名称树本质上是一个树形图,允许快速访问命名值,而不需要一次读取所有数据(就像使用普通字典一样)。 不幸的是,在Quartz中没有对名称树的直接支持,所以你需要做更多的工作来recursion地parsing这个结构(参见PDF规范中的“名称树”)。

请注意,大纲项目不一定具有/Dest条目,它也可以通过/A (动作)条目来指定其目的地,这有点复杂。 然而,在大多数情况下,这个动作将是一个“GoTo”动作,它本质上是一个目的地的包装。

名称到目的地的映射也可以作为普通字典存储。 在这种情况下,它位于文档目录中/ Names字典的/Dests项中。 我很less看到这个,但在PDF 1.2(当前是1.7)之后已经被弃用了。

你肯定会需要这个PDF规范: http : //www.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/PDF32000_2008.pdf

感谢Omz,下面是一段代码,用于在PDF文件中检索大纲目的地的页码:

 // Get Page Number from an array - (int) getPageNumberFromArray:(CGPDFArrayRef)array ofPdfDoc:(CGPDFDocumentRef)pdfDoc withNumberOfPages:(int)numberOfPages { int pageNumber = -1; // Page number reference is the first element of array (el 0) CGPDFDictionaryRef pageDic; CGPDFArrayGetDictionary(array, 0, &pageDic); // page searching for (int p=1; p<=numberOfPages; p++) { CGPDFPageRef page = CGPDFDocumentGetPage(pdfDoc, p); if (CGPDFPageGetDictionary(page) == pageDic) { pageNumber = p; break; } } return pageNumber; } // Get page number from an outline. Only support "Dest" and "A" entries - (int) getPageNumber:(CGPDFDictionaryRef)node ofPdfDoc:(CGPDFDocumentRef)pdfDoc withNumberOfPages:(int)numberOfPages { int pageNumber = -1; CGPDFArrayRef destArray; CGPDFDictionaryRef dicoActions; if(CGPDFDictionaryGetArray(node, "Dest", &destArray)) { pageNumber = [self getPageNumberFromArray:destArray ofPdfDoc:pdfDoc withNumberOfPages:numberOfPages]; } else if(CGPDFDictionaryGetDictionary(node, "A", &dicoActions)) { const char * typeOfActionConstChar; CGPDFDictionaryGetName(dicoActions, "S", &typeOfActionConstChar); NSString * typeOfAction = [NSString stringWithUTF8String:typeOfActionConstChar]; if([typeOfAction isEqualToString:@"GoTo"]) // only support "GoTo" entry. See PDF spec p653 { CGPDFArrayRef dArray; if(CGPDFDictionaryGetArray(dicoActions, "D", &dArray)) { pageNumber = [self getPageNumberFromArray:dArray ofPdfDoc:pdfDoc withNumberOfPages:numberOfPages]; } } } return pageNumber; }