Note that there are some explanatory texts on larger screens.

plurals
  1. POGet PDF hyperlinks on iOS with Quartz
    text
    copied!<p>I've spent all day trying to get hyperlinks metadata from PDFs in my iPad application. The CGPDF* APIs are a true nightmare, and the only piece of information I've found on the net about all this is that I have to look for an "Annots" dictionary, but I just can't find it in my PDFs. </p> <p>I even used the old <a href="https://github.com/below/PDF-Voyeur/network" rel="nofollow noreferrer">Voyeur Xcode sample</a> to inspect my test PDF file, but no trace of this "Annots" dictionary...</p> <p>You know, this is a feature I see on every PDF reader - this same question has <a href="https://stackoverflow.com/questions/93297/newbie-wants-to-create-a-pdf-reader-for-ipod-touch-whats-the-best-approach">been</a> <a href="https://stackoverflow.com/questions/3257057/iphone-cgpdfdocument-pdf-links">asked</a> <a href="https://stackoverflow.com/questions/2609602/pdf-hyperlinks-on-iphone-ipad">multiple</a> <a href="https://stackoverflow.com/questions/1247792/how-to-access-hyperlinks-in-pdf-documents-iphone">times</a> here with no real practical answers. I usually never ask for sample code directly but apparently this time I really need it... anyone got this working, possibly with sample code?</p> <p><strong>Update</strong>: I just realized the guy who has done my testing PDF had just inserted an URL as text, and not a real annotation. He tried putting an annotation and my code works now... But that's not what I need, so it seems I'll have to analyze text and search for URLs. But that's another story... </p> <p><strong>Update 2</strong>: So I finally came up with some working code. I'm posting it here so hopefully it'll help someone. It assumes the PDF document actually contains annotations. </p> <pre><code>for(int i=0; i&lt;pageCount; i++) { CGPDFPageRef page = CGPDFDocumentGetPage(doc, i+1); CGPDFDictionaryRef pageDictionary = CGPDFPageGetDictionary(page); CGPDFArrayRef outputArray; if(!CGPDFDictionaryGetArray(pageDictionary, "Annots", &amp;outputArray)) { return; } int arrayCount = CGPDFArrayGetCount( outputArray ); if(!arrayCount) { continue; } for( int j = 0; j &lt; arrayCount; ++j ) { CGPDFObjectRef aDictObj; if(!CGPDFArrayGetObject(outputArray, j, &amp;aDictObj)) { return; } CGPDFDictionaryRef annotDict; if(!CGPDFObjectGetValue(aDictObj, kCGPDFObjectTypeDictionary, &amp;annotDict)) { return; } CGPDFDictionaryRef aDict; if(!CGPDFDictionaryGetDictionary(annotDict, "A", &amp;aDict)) { return; } CGPDFStringRef uriStringRef; if(!CGPDFDictionaryGetString(aDict, "URI", &amp;uriStringRef)) { return; } CGPDFArrayRef rectArray; if(!CGPDFDictionaryGetArray(annotDict, "Rect", &amp;rectArray)) { return; } int arrayCount = CGPDFArrayGetCount( rectArray ); CGPDFReal coords[4]; for( int k = 0; k &lt; arrayCount; ++k ) { CGPDFObjectRef rectObj; if(!CGPDFArrayGetObject(rectArray, k, &amp;rectObj)) { return; } CGPDFReal coord; if(!CGPDFObjectGetValue(rectObj, kCGPDFObjectTypeReal, &amp;coord)) { return; } coords[k] = coord; } char *uriString = (char *)CGPDFStringGetBytePtr(uriStringRef); NSString *uri = [NSString stringWithCString:uriString encoding:NSUTF8StringEncoding]; CGRect rect = CGRectMake(coords[0],coords[1],coords[2],coords[3]); CGPDFInteger pageRotate = 0; CGPDFDictionaryGetInteger( pageDictionary, "Rotate", &amp;pageRotate ); CGRect pageRect = CGRectIntegral( CGPDFPageGetBoxRect( page, kCGPDFMediaBox )); if( pageRotate == 90 || pageRotate == 270 ) { CGFloat temp = pageRect.size.width; pageRect.size.width = pageRect.size.height; pageRect.size.height = temp; } rect.size.width -= rect.origin.x; rect.size.height -= rect.origin.y; CGAffineTransform trans = CGAffineTransformIdentity; trans = CGAffineTransformTranslate(trans, 0, pageRect.size.height); trans = CGAffineTransformScale(trans, 1.0, -1.0); rect = CGRectApplyAffineTransform(rect, trans); // do whatever you need with the coordinates. // e.g. you could create a button and put it on top of your page // and use it to open the URL with UIApplication's openURL } } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload