How to combine two pdfs without losing any information?

1.7k Views Asked by At

My goal is to combine two PDFs. One has 10 pages, and another has 6 pages, so the output should be 16 pages. My approach is to load both PDFs into two NSData stored in an NSMutableArray.

Here is my saving method:

NSMutableData *toSave = [NSMutableData data];
for(NSData *pdf in PDFArray){
    [toSave appendData:pdf];
}
[toSave writeToFile:path atomically:YES];

However the output PDF only has the second part, which only contains 6 pages. So I don't know what did I miss. Can anyone give me some hints?

2

There are 2 best solutions below

2
clemens On BEST ANSWER

PDF is a file format which describes a single document. You cannot concatenate to PDF files to get the concatenated document.

But might achieve this with PDFKit:

  1. Create both documents with initWithData:.
  2. Insert all pages of the second document into the first one with insertPage:atIndex:.

This should look like:

PDFDocument *theDocument = [[PDFDocument alloc] initWithData:PDFArray[0]]
PDFDocument *theSecondDocument = [[PDFDocument alloc] initWithData:PDFArray[1]]
NSInteger theCount = theDocument.pageCount;
NSInteger theSecondCount = theSecondDocument.pageCount;

for(NSInteger i = 0; i < theSecondCount; ++i) {
    PDFPage *thePage = [theSecondDocument pageAtIndex:i];

    [theDocument insertPage:thePage atIndex:theCount + i];
}
[theDocument writeToURL:theTargetURL];

You have to add either #import <PDFKit/PDFKit.h> or @import PDFKit; to your source file, and you should add PDFKit.framework to the Linked Frameworks and Libraries of the build target in Xcode.

0
Daan On

I've made a Swift command line tool to combine any number of PDF files. It takes the output path as the first argument and the input PDF files as the other arguments. There's no error handling whatsoever, so you can add that if you want to. Here's the full code:

import PDFKit

let args = CommandLine.arguments.map { URL(fileURLWithPath: $0) }
let doc = PDFDocument(url: args[2])!

for i in 3..<args.count {
    let docAdd = PDFDocument(url: args[i])!
    for i in 0..<docAdd.pageCount {
        let page = docAdd.page(at: i)!
        doc.insert(page, at: doc.pageCount)
    }
}
doc.write(to: args[1])