How can I read-modify-write a PDF (CGPDFDocument)

2019-05-10 20:25发布

问题:

I am trying to modify the PDF metadata (title, author, etc.) of an existing PDF on iOS. While it is easy to find sample code for PDF parsing and for PDF creation from scratch, there does not seem to be an easy way to dump an existing PDF into a new file - and modify it just slightly.

More specifically, how do I get the info obtained when reading a PDF roughly like this:

CGPDFDocumentRef myPDF = CGPDFDocumentCreateWithURL((CFURLRef)urlOfInputPDF);
CGPDFDictionaryRef myPDFDict=CGPDFDocumentGetInfo(myPDF);

into the new PDF, which I would create roughly this way:

CGRect pageRect;
CFMutableDictionaryRef myDictionary = CFDictionaryCreateMutable(NULL, 0,
                                         &kCFTypeDictionaryKeyCallBacks,
                                         &kCFTypeDictionaryValueCallBacks);
CFDictionarySetValue(myDictionary, kCGPDFContextTitle, CFSTR("My PDF File"));
CFDictionarySetValue(myDictionary, kCGPDFContextCreator, CFSTR("My Name"));
pdfContext = CGPDFContextCreateWithURL (urlOfOutputPDF, &pageRect, myDictionary);

Obviously, the dictionary types do not match, and the output created this way is page (not document) related.

Any ideas, how I can copy the whole CGPDFDocumentRef into a new file? And how to make it mutable, so I can modify the meta data before saving?

回答1:

I'm not aware of a way with CoreGraphics than to iterate over each page and print them into the new document. At least that's what I'm doing in PSPDFKit. And re-rendering a whole document is quite slow for larger documents.

You also loose some metadata when you go that way - maybe a much more direct manipulation of the PDF is a better way - but note that you need to update the xref trailer in the PDF if you directly edit strings, since the trailer is a map of byte-coordinates that will change once you add/delete characters.



回答2:

Don't use CGPDFDocument (Core Graphics); use PDFDocument (PDFKit) instead. That provides much easier methods for this kind of thing.

The writeToFile:withOptions method lets you save the PDF to a new file, specifying the DOCINFO data in a dictionary.