Create PDF from UIView
You can easily create a PDF file fromUIView
. Create an Extension of UIView
and add below code in your UIView Extension
file.
Extension UIView {
// Export pdf from Save pdf in drectory and return pdf file path
func exportAsPdfFromView() -> String {
let pdfPageFrame = self.bounds
let pdfData = NSMutableData()
UIGraphicsBeginPDFContextToData(pdfData, pdfPageFrame, nil)
UIGraphicsBeginPDFPageWithInfo(pdfPageFrame, nil)
guard let pdfContext = UIGraphicsGetCurrentContext() else { return "" }
self.layer.render(in: pdfContext)
UIGraphicsEndPDFContext()
return self.saveViewPdf(data: pdfData)
}
// Save pdf file in document directory
func saveViewPdf(data: NSMutableData) -> String {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let docDirectoryPath = paths[0]
let pdfPath = docDirectoryPath.appendingPathComponent("viewPdf.pdf")
if data.write(to: pdfPath, atomically: true) {
return pdfPath.path
} else {
return ""
}
}
}
Now using above Extension
you can export to PDF of any UIView
and it will save PDF file in directory and return it’s path. Suppose you want to create a PDF from self.view
then write below code.
let pdfFilePath = self.view.exportAsPdfFromView()
print(pdfFilePath)
Create PDF from WKWebView
We are going to create an Extension ofWKWebView
and Extension of UIPrintPageRenderer
. With the help of UIPrintPageRenderer
we will create NSMutableData
to render PDF file from WKWebView
. Add below Extensions in your file.
extension WKWebView {
// Call this function when WKWebView finish loading
func exportAsPdfFromWebView() -> String {
let pdfData = createPdfFile(printFormatter: self.viewPrintFormatter())
return self.saveWebViewPdf(data: pdfData)
}
func createPdfFile(printFormatter: UIViewPrintFormatter) -> NSMutableData {
let originalBounds = self.bounds
self.bounds = CGRect(x: originalBounds.origin.x, y: bounds.origin.y, width: self.bounds.size.width, height: self.scrollView.contentSize.height)
let pdfPageFrame = CGRect(x: 0, y: 0, width: self.bounds.size.width, height: self.scrollView.contentSize.height)
let printPageRenderer = UIPrintPageRenderer()
printPageRenderer.addPrintFormatter(printFormatter, startingAtPageAt: 0)
printPageRenderer.setValue(NSValue(cgRect: UIScreen.main.bounds), forKey: "paperRect")
printPageRenderer.setValue(NSValue(cgRect: pdfPageFrame), forKey: "printableRect")
self.bounds = originalBounds
return printPageRenderer.generatePdfData()
}
// Save pdf file in document directory
func saveWebViewPdf(data: NSMutableData) -> String {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let docDirectoryPath = paths[0]
let pdfPath = docDirectoryPath.appendingPathComponent("webViewPdf.pdf")
if data.write(to: pdfPath, atomically: true) {
return pdfPath.path
} else {
return ""
}
}
}
extension UIPrintPageRenderer {
func generatePdfData() -> NSMutableData {
let pdfData = NSMutableData()
UIGraphicsBeginPDFContextToData(pdfData, self.paperRect, nil)
self.prepare(forDrawingPages: NSMakeRange(0, self.numberOfPages))
let printRect = UIGraphicsGetPDFContextBounds()
for pdfPage in 0..< self.numberOfPages {
UIGraphicsBeginPDFPage()
self.drawPage(at: pdfPage, in: printRect)
}
UIGraphicsEndPDFContext();
return pdfData
}
}
Now we can create PDF from any WKWebView
. Write below code to create PDF file of WKWebView
.
let pdfFilePath = self.webView.exportAsPdfFromWebView()
print(pdfFilePath)
Create PDF from UITableView
Again we will create an Extension ofUITableView
and using this Extension we can create PDF file of any UITableView
extension UITableView {
// Export pdf from UITableView and save pdf in drectory and return pdf file path
func exportAsPdfFromTable() -> String {
let originalBounds = self.bounds
self.bounds = CGRect(x:originalBounds.origin.x, y: originalBounds.origin.y, width: self.contentSize.width, height: self.contentSize.height)
let pdfPageFrame = CGRect(x: 0, y: 0, width: self.bounds.size.width, height: self.contentSize.height)
let pdfData = NSMutableData()
UIGraphicsBeginPDFContextToData(pdfData, pdfPageFrame, nil)
UIGraphicsBeginPDFPageWithInfo(pdfPageFrame, nil)
guard let pdfContext = UIGraphicsGetCurrentContext() else { return "" }
self.layer.render(in: pdfContext)
UIGraphicsEndPDFContext()
self.bounds = originalBounds
// Save pdf data
return self.saveTablePdf(data: pdfData)
}
// Save pdf file in document directory
func saveTablePdf(data: NSMutableData) -> String {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let docDirectoryPath = paths[0]
let pdfPath = docDirectoryPath.appendingPathComponent("tablePdf.pdf")
if data.write(to: pdfPath, atomically: true) {
return pdfPath.path
} else {
return ""
}
}
}
Now in order to generate PDF from UITableView
write below code.
let pdfFilePath = self.tableView.exportAsPdfFromTable()
print(pdfFilePath)
Read next article: The dynamic height of UITextView inside UITableViewCell Swift
The quality of the PDF saved is very low. How can i increase the quality of the PDFs ? And also how can i make a PDF with more than 1 page?
Perfectly composed content material, appreciate it for information .
Can’t access the saved file on my device, can you please help me on the path that it will be accessible to my users
Currently, pdf is being saved in the application documents directory, you can add a code to open mail composer and attached this pdf.
Please i can’t access the saved pdf on my iphone
This is really great but for what ever reason intermittently creates a blank pdf! does anyone know how to resolve this?
I get the blank file when export pdf for UITableView
Good article. I’m going through some of these issues as well..
Nice but
The background of table view (or cell must be ignored)
the pdf generated have a very big dimension (120 MB for me) it’s possible to resize? (maybe with a parameter)
the pdf is not possible to share or show in UIDocumentPreview / uiactivity etc…
There is a easy way to print or save correctly?
This article is great. I’am new into XCode/Swift/iOS. I have one question, I am working on a tabbed app.
I like to save all the tabbed Views to one pdf. With the sample above, I can save seperate views. Can
you give me a hint how to accomplish this?
Thanks and best regards,
Marc