Tuesday, 20 October 2020

Swift iOS - Overlay text onto PDF with PDFKit and UI

I'm working in Swift 5 and on iOS. I'm trying to overlay text onto a current PDF I have. I'm essentially porting code I made from an app for macOS. This is the code from the Mac version:

func executeContext(at srcURL: URL, to dstURL: URL) {

// Confirm there is a document there
if let doc: PDFDocument = PDFDocument(url: srcURL) {
    
    // Create a document, get the first page, and set the size of the page
    let page: PDFPage = doc.page(at: 0)!
    var mediaBox: CGRect = CGRect(x: 0, y: 0, width: 792, height: 612)
    
    // This is where the magic happens.  Create the drawing context on the PDF
    let context = CGContext(dstURL as CFURL, mediaBox: &mediaBox, nil)
    let graphicsContext = NSGraphicsContext(cgContext: context!, flipped: false)
    NSGraphicsContext.current = graphicsContext
    
    context!.beginPDFPage(nil)
    
    // Draws the PDF into the context
    page.draw(with: .mediaBox, to: context!)
    
    // Parse and Draw Text on the context
    //drawText()
    
    let attributes = [
        NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 72)
    ]
    let text = "I'm a PDF!"
    text.draw(at: CGPoint(x: 0, y: 0), withAttributes: attributes)
    
    context!.saveGState()
    
    context!.restoreGState()
    
    context!.endPDFPage()
    NSGraphicsContext.current = nil
    context?.closePDF()
}
}

The drawText() function did most of the text overlaying that was needed, but I put another "draw "method below it to test it out.

I'm understandably getting an error "Cannot find 'NSGraphicsContext' in scope" since NSGraphicsContext doesn't exist on iOS. I've tried to find an equivalent translation with UIGraphicsPDFRenderer or UIGraphicsBeginPDFContextToData, and using some code from a Ray Wenderlich tutorial, I was able to create a new PDF and place text on it with the below code:

func createDocument(url: URL) -> Data {

//let pdfData = try? Data.init(contentsOf: url)

// 1
let pdfMetaData = [
    kCGPDFContextCreator: "Timecard App",
    kCGPDFContextAuthor: "Timecard App"
]
let format = UIGraphicsPDFRendererFormat()
format.documentInfo = pdfMetaData as [String: Any]

// 2
let pageWidth = 8.5 * 72.0
let pageHeight = 11 * 72.0
let pageRect = CGRect(x: 0, y: 0, width: pageWidth, height: pageHeight)

// 3
let renderer = UIGraphicsPDFRenderer(bounds: pageRect, format: format)

// 4
let data = renderer.pdfData { (context) in
    // 5
    context.beginPage()
    // 6
    let attributes = [
        NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 72)
    ]
    let text = "I'm a PDF!"
    text.draw(at: CGPoint(x: 0, y: 0), withAttributes: attributes)
}

return data

}

...but I couldn't find a way to load in current PDF "data" to the renderer and then draw from there. Does anyone have any suggestions on the proper way to do this?



from Swift iOS - Overlay text onto PDF with PDFKit and UI

No comments:

Post a Comment