Search code examples
htmlswiftpdfkit

Add a page break in html for PDFKit in Swift


I'm creating a PDF with HTML and PDFKit as follows:


let contextString = "<p style=\"page-break-after: always;\">hello</p><p>This is a test</p>"

let print = UIMarkupTextPrintFormatter(markupText: contextString)

let render = UIPrintPageRenderer()
render.addPrintFormatter(print, startingAtPageAt: 0)

let page = CGRect(x: 0, y: 0, width: 595.2, height: 841.8) // A4, 72 dpi
render.setValue(page, forKey: "paperRect")
render.setValue(page, forKey: "printableRect")

let pdfData = NSMutableData()
UIGraphicsBeginPDFContextToData(pdfData, .zero, nil)

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

let av = UIActivityViewController(activityItems: [pdfData], applicationActivities: nil)

UIApplication.shared.windows.first?.rootViewController?.present(av, animated: true, completion: nil)

I added a page break after the first <p>. This works a bit to well. It makes two page breaks and the 2nd <p> doesn't show at all.

Does anyone have experience with that?
How can I add a page break in the PDF?


Solution

  • I was able to get your code working with a single change to your contextString.

    By changing it to page-break-before instead of page-break-after it seems to work. This is what I changed your contextString to, I used a multiline string as it is easier to read and gave it some clearer content.

    let contextString = """
    <p>Content in page 1</p>
    <p style=\"page-break-before: always;\"></p>
    <p>Content in page 2</p>
    """
    

    Here is a very simple example that you could drop into Xcode.

    class ViewController: UIViewController {
    
        let button = UIButton()
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view.
            view.addSubview(button)
            button.translatesAutoresizingMaskIntoConstraints = false
    
            button.setTitle("Print", for: .normal)
            button.setTitleColor(.systemBlue, for: .normal)
            button.addTarget(self, action: #selector(tapped), for: .touchUpInside)
    
            NSLayoutConstraint.activate([
                button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
                button.centerYAnchor.constraint(equalTo: view.centerYAnchor),
                button.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
            ])
            view.backgroundColor = .systemBackground
        }
    
        @objc func tapped() {
    
            let contextString = """
            <p>Content in page 1</p>
            <p style=\"page-break-before: always;\"></p>
            <p>Content in page 2</p>
            """
    
            let print = UIMarkupTextPrintFormatter(markupText: contextString)
    
    
            let render = UIPrintPageRenderer()
            render.addPrintFormatter(print, startingAtPageAt: 0)
    
            let page = CGRect(x: 0, y: 0, width: 595.2, height: 841.8) // A4, 72 dpi
            render.setValue(page, forKey: "paperRect")
            render.setValue(page, forKey: "printableRect")
    
            let pdfData = NSMutableData()
            UIGraphicsBeginPDFContextToData(pdfData, .zero, nil)
    
            for i in 0..<render.numberOfPages {
            UIGraphicsBeginPDFPage();
                render.drawPage(at: i, in: UIGraphicsGetPDFContextBounds())
            }
            UIGraphicsEndPDFContext();
    
            let av = UIActivityViewController(activityItems: [pdfData], applicationActivities: nil)
    
            self.present(av, animated: true, completion: nil)
        }
    }
    

    Here is a gif of it showing the two pages with the text:

    gif showing text added to both pages