iosdev

Convert HTML into PDF on iOS

There are multiple ways to generate PDF files on the iOS and most employ learning and mastering a new framework. Which is not an easy task. Add-in the fact that it’s far easier to generate HTML – at least for me – it makes sense to investigate how hard it is to “print” that web page into PDF.

It turns out, not hard at all.

UIPrintPageRenderer is relatively simple class to use and documentation is fairly easy to understand.

let renderer = UIPrintPageRenderer()

It’s not doing anything until you give it an instance of UIViewPrintFormatter. WKWebView inherits from UIView, thus it’s easy to connect it with the print page renderer.

renderer.addPrintFormatter(webView.viewPrintFormatter(), startingAtPageAt: 0)

This UIPrintPageRenderer instance has two read-only properties that are interesting to us:

Heh…iOS is beautiful Objective-C based dynamic runtime where we can use KVC to change the values of any properties, read-only or not:

enum Key: String {
	case paperRect
	case printableRect
}

let a4 = CGSize(width: 595.2, height: 841.8)
let paperRect = CGRect(x: 0, y: 0, width: a4.width, height: a4.height)
renderer.setValue(paperRect, forKey: Key.paperRect.rawValue)

var printableRect = paperRect
// adjust printableRect as you need, add padding or whatever
renderer.setValue(printableRect, forKey: Key.printableRect.rawValue)

Now, actually making the PDF is now surprisingly simple, you simply call a method like this:

extension UIPrintPageRenderer {
	public func makePDF() -> Data {
		let data = NSMutableData()

		UIGraphicsBeginPDFContextToData(data, paperRect, nil)
		prepare(forDrawingPages: NSMakeRange(0, numberOfPages))
		let bounds = UIGraphicsGetPDFContextBounds()

		for i in 0 ..< numberOfPages {
			UIGraphicsBeginPDFPage()
			drawPage(at: i, in: bounds)
		}
		UIGraphicsEndPDFContext()

		return data as Data
	}
}

This is the heart of the simple micro-library HTML2PDFRenderer I just published on GitHub.