Notice: I working with swift 4 for osx. I would like to generate a pdf file from a WebView.
At the moment my WebView load a html-string and show this successfully. If I press a button, the print panel will open and is ready to print my WebView content in the correct format.
This is my print code:
var webView = WebView()
var htmlString = "MY HTML STRING"
override func viewDidLoad() {
webView.mainFrame.loadHTMLString(htmlString, baseURL: nil)
}
func webView(_ sender: WebView!, didFinishLoadFor frame: WebFrame!) {
let printInfo = NSPrintInfo.shared
printInfo.paperSize = NSMakeSize(595.22, 841.85)
printInfo.isHorizontallyCentered = true
printInfo.isVerticallyCentered = true
printInfo.orientation = .portrait
printInfo.topMargin = 50
printInfo.rightMargin = 0
printInfo.bottomMargin = 50
printInfo.leftMargin = 0
printInfo.verticalPagination = .autoPagination
printInfo.horizontalPagination = .fitPagination
//webView.mainFrame.frameView.printOperation(with: printInfo).run()
let printOp: NSPrintOperation = NSPrintOperation(view: webView.mainFrame.frameView.documentView, printInfo: printInfo)
printOp.showsPrintPanel = true
printOp.showsProgressPanel = false
printOp.run()
}
Now I would like to have another button, which save the content directly as a pdf file.
I tried this:
let pdfData = webView.mainFrame.frameView.documentView.dataWithPDF(inside: webView.mainFrame.frameView.documentView.frame)
let document = PDFDocument(data: pdfData)
let fileURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false).appendingPathComponent("myPDF.pdf")
document?.write(to: fileURL)
But the result of my pdf looks horrible:
Have anybody an idea?
UPDATE This is a part of my web view result:
and that is the result of my print preview / pdf file /the color is missing, but now everywhere. the "logo"(picture) will show with color:
The problem is that dataWithPDF
uses the view's current frame to decide how wide the generated PDF should be. Since your WebView
's frame in your app is probably skinnier than an 8.5/11" page, you're getting a PDF that is inadequately wide. You could adjust the WebView
's frame to the right size, make the PDF, and then adjust it back, or you could create a new WebView
, render it offscreen, set it to the appropriate size, and create the PDF. That's a bit of a pain in the backside, though. Wouldn't it be great if there were a way to programatically do what the "PDF" button in the Print dialog does, since the print system handles all this stuff for you automatically?
Well, turns out you can! But you have to dive into the poorly-documented world of Core Printing.
func makePDF(at url: URL, for webView: WebView, printInfo: NSPrintInfo) throws {
webView.preferences.shouldPrintBackgrounds = true
guard let printOp = webView.mainFrame.frameView.printOperation(with: printInfo) else {
throw MyPrintError.couldntGetPrintOperation // or something like this
}
let session = PMPrintSession(printOp.printInfo.pmPrintSession())
let settings = PMPrintSettings(printOp.printInfo.pmPrintSettings())
if PMSessionSetDestination(session,
settings,
PMDestinationType(kPMDestinationFile),
kPMDocumentFormatPDF as CFString,
url as CFURL) != noErr {
throw MyPrintError.couldntSetDestination // or something like this
}
printOp.showsPrintPanel = false
printOp.run()
}
The key is the PMSessionSetDestination
call, which allows us to configure the print session to print to a PDF instead of to an actual printer. Then we just tell NSPrintOperation
not to show the print panel, run the operation, and presto! PDF printed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With