Search code examples
swiftpdfcgcontextios-pdfkitapple-pdfkit

Swift PDFKit draw multiple images in a single PDFPage


I'm trying to draw multiple images into a single PDFPage.
Looking at the docs and over StackOverflow seems like the best I got is to use PDFPage with an UIImage initializer like so:

let pdfPage = PDFPage(image: image)

But it just creates a page with a full-page image. I tried to draw the images using CGContext but I don't understand how to use PDFPage within a drawing context for it to draw the images rapidly like in the example below.

let bounds = page.bounds(for: .cropBox)

// Create a `UIGraphicsImageRenderer` to use for drawing an image.
let renderer = UIGraphicsImageRenderer(bounds: bounds, format: UIGraphicsImageRendererFormat.default())

let image = renderer.image { (context) in

 // How do I rapidly draw them here?

}

Any help will be highly appreciated!

The result I get with PDFPage(image: <UIImage>) vs expected result:

enter image description here


Solution

  • You probably need to improve the positioning logic for the image in the loop, but this should point you to the right direction.

    import UIKit
    import PDFKit
    
    class ViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
                  
            let pdfView = PDFView()
            pdfView.frame = CGRect(x: 0, y: 50, width: view.frame.width, height: view.frame.height - 50)
            if let d = createPDFDocument() {
                pdfView.document = d
            }
            
            view.addSubview(pdfView)
        }
    
        func createPDFDocument() -> PDFDocument? {
            let pdfDocument = PDFDocument()
            let page = PDFPage()
            let bounds = page.bounds(for: .cropBox)
            let imageRenderer = UIGraphicsImageRenderer(bounds: bounds, format: UIGraphicsImageRendererFormat.default())
            let image = imageRenderer.image { (context) in
                context.cgContext.saveGState()
                context.cgContext.translateBy(x: 0, y: bounds.height)
                context.cgContext.concatenate(CGAffineTransform.init(scaleX: 1, y: -1))
                page.draw(with: .mediaBox, to: context.cgContext)
                context.cgContext.restoreGState()
    
                // Improve logic for image position
                Range(1...4).forEach { value in
                    let image = UIImage(named: "YOUR_IMAGE_NAME")
                    let rect = CGRect(x: 50 * value, y: 0, width: 40, height: 100)
                    image?.draw(in: rect)
                }
            }
            
            let newPage = PDFPage(image: image)!
            pdfDocument.insert(newPage, at: 0)
    
            return pdfDocument
        }
    }