How to Convert UIView to PDF within iOS?
Solution 1
Note that the following method creates just a bitmap of the view; it does not create actual typography.
(void)createPDFfromUIView:(UIView*)aView saveToDocumentsWithFileName:(NSString*)aFilename
{
// Creates a mutable data object for updating with binary data, like a byte array
NSMutableData *pdfData = [NSMutableData data];
// Points the pdf converter to the mutable data object and to the UIView to be converted
UIGraphicsBeginPDFContextToData(pdfData, aView.bounds, nil);
UIGraphicsBeginPDFPage();
CGContextRef pdfContext = UIGraphicsGetCurrentContext();
// draws rect to the view and thus this is captured by UIGraphicsBeginPDFContextToData
[aView.layer renderInContext:pdfContext];
// remove PDF rendering context
UIGraphicsEndPDFContext();
// Retrieves the document directories from the iOS device
NSArray* documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
NSString* documentDirectory = [documentDirectories objectAtIndex:0];
NSString* documentDirectoryFilename = [documentDirectory stringByAppendingPathComponent:aFilename];
// instructs the mutable data object to write its context to a file on disk
[pdfData writeToFile:documentDirectoryFilename atomically:YES];
NSLog(@"documentDirectoryFileName: %@",documentDirectoryFilename);
}
Also make sure you import: QuartzCore/QuartzCore.h
Solution 2
Additionally, if anyone is interested, here is the Swift 3 code:
func createPdfFromView(aView: UIView, saveToDocumentsWithFileName fileName: String)
{
let pdfData = NSMutableData()
UIGraphicsBeginPDFContextToData(pdfData, aView.bounds, nil)
UIGraphicsBeginPDFPage()
guard let pdfContext = UIGraphicsGetCurrentContext() else { return }
aView.layer.render(in: pdfContext)
UIGraphicsEndPDFContext()
if let documentDirectories = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first {
let documentsFileName = documentDirectories + "/" + fileName
debugPrint(documentsFileName)
pdfData.write(toFile: documentsFileName, atomically: true)
}
}
Solution 3
If someone is interested, here's Swift 2.1 code:
func createPdfFromView(aView: UIView, saveToDocumentsWithFileName fileName: String)
{
let pdfData = NSMutableData()
UIGraphicsBeginPDFContextToData(pdfData, aView.bounds, nil)
UIGraphicsBeginPDFPage()
guard let pdfContext = UIGraphicsGetCurrentContext() else { return }
aView.layer.renderInContext(pdfContext)
UIGraphicsEndPDFContext()
if let documentDirectories = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first {
let documentsFileName = documentDirectories + "/" + fileName
debugPrint(documentsFileName)
pdfData.writeToFile(documentsFileName, atomically: true)
}
}
Solution 4
A super easy way to create a PDF from UIView is using UIView Extension
Swift 4.2
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 ""
}
}
}
Credit: http://www.swiftdevcenter.com/create-pdf-from-uiview-wkwebview-and-uitableview/
Solution 5
With Swift 5 / iOS 12, you can combine CALayer
's render(in:)
method with UIGraphicsPDFRenderer
's writePDF(to:withActions:)
method in order to create a PDF file from a UIView
instance.
The following Playground sample code shows how to use render(in:)
and writePDF(to:withActions:)
:
import UIKit
import PlaygroundSupport
let view = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
view.backgroundColor = .orange
let subView = UIView(frame: CGRect(x: 20, y: 20, width: 40, height: 60))
subView.backgroundColor = .magenta
view.addSubview(subView)
let outputFileURL = PlaygroundSupport.playgroundSharedDataDirectory.appendingPathComponent("MyPDF.pdf")
let pdfRenderer = UIGraphicsPDFRenderer(bounds: view.bounds)
do {
try pdfRenderer.writePDF(to: outputFileURL, withActions: { context in
context.beginPage()
view.layer.render(in: context.cgContext)
})
} catch {
print("Could not create PDF file: \(error)")
}
Note: in order to use playgroundSharedDataDirectory
in your Playground, you first need to create a folder called "Shared Playground Data" in you macOS "Documents" folder.
The UIViewController
subclass complete implementation below shows a possible way to refactor the previous example for an iOS app:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let view = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
view.backgroundColor = .orange
let subView = UIView(frame: CGRect(x: 20, y: 20, width: 40, height: 60))
subView.backgroundColor = .magenta
view.addSubview(subView)
createPDF(from: view)
}
func createPDF(from view: UIView) {
let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let outputFileURL = documentDirectory.appendingPathComponent("MyPDF.pdf")
print("URL:", outputFileURL) // When running on simulator, use the given path to retrieve the PDF file
let pdfRenderer = UIGraphicsPDFRenderer(bounds: view.bounds)
do {
try pdfRenderer.writePDF(to: outputFileURL, withActions: { context in
context.beginPage()
view.layer.render(in: context.cgContext)
})
} catch {
print("Could not create PDF file: \(error)")
}
}
}
Comments
-
Cullen SUN over 3 years
There are a lot of resources about how to display a PDF in an App's
UIView
. What I am working on now is to create a PDF fromUIViews
.For example, I have a
UIView
, with subviews like Textviews,UILabels
,UIImages
, so how can I convert a bigUIView
as a whole including all its subviews and subsubviews to a PDF?I have checked Apple's iOS reference. However, it only talks about writing pieces of text/image to a PDF file.
The problem I am facing is that the content I want to write to a file as PDF is a lot. If I write them to the PDF piece by piece, it is going to be huge work to do. That's why I am looking for a way to write
UIViews
to PDFs or even bitmaps.I have tried the source code I copied from other Q/A within Stack Overflow. But it only gives me a blank PDF with the
UIView
bounds size.-(void)createPDFfromUIView:(UIView*)aView saveToDocumentsWithFileName:(NSString*)aFilename { // Creates a mutable data object for updating with binary data, like a byte array NSMutableData *pdfData = [NSMutableData data]; // Points the pdf converter to the mutable data object and to the UIView to be converted UIGraphicsBeginPDFContextToData(pdfData, aView.bounds, nil); UIGraphicsBeginPDFPage(); // draws rect to the view and thus this is captured by UIGraphicsBeginPDFContextToData [aView drawRect:aView.bounds]; // remove PDF rendering context UIGraphicsEndPDFContext(); // Retrieves the document directories from the iOS device NSArray* documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES); NSString* documentDirectory = [documentDirectories objectAtIndex:0]; NSString* documentDirectoryFilename = [documentDirectory stringByAppendingPathComponent:aFilename]; // instructs the mutable data object to write its context to a file on disk [pdfData writeToFile:documentDirectoryFilename atomically:YES]; NSLog(@"documentDirectoryFileName: %@",documentDirectoryFilename); }
-
Jason George over 12 years+1 I went through several posts on pdf generation before finding this simple solution.
-
iEamin over 12 yearsI wanted to do the same and your method seems to work fine but its quality is very low. Did I miss anything?
-
joshaidan almost 12 yearsI suspect the quality is pretty low because it's taking the UIView and converting it to a raster, where as the other methods of rendering text and images directly preserves them as vectors in the PDF file.
-
Raj over 11 yearsI am following this method , but I am getting a blank pdf generated . can any one help me ?
-
Rudi about 11 yearsIt works awesome !!! cheers !! the only problem that I have is, it generate PDF in just one page. How can i Separate pages instead of having a long PDF file ?!
-
Alex Stone about 11 yearsGives me a blank screen on iOS6.1
-
casillic about 11 yearsThis is the same exact code as my answer just broken out in two separate methods???? How do you think this fixed your blank screen problem when it is the same code??
-
Paresh Masani almost 11 yearsHi this works fine but it doesn't create pdf for whole uitableview. Can you please suggest how to take pdf for invisible cells as well?
-
Grant B almost 11 yearsSeems this works ok. Except if the view scrolls. In which case it only renders visible content. I imagine aview.bounds is controlling this ?
-
NashT over 10 yearsI found that I was getting a blank screen when I ran the code on the view did load method. Maybe try and run the method when a button is pressed or something and it should be fine. The quality is fantastic thanks Casillic!
-
Daniel Arantes Loverde over 10 yearsiOS 5.1 get half page, is there normal ?
-
shim over 10 yearsThis draws my view such that it fills the page. If I use drawInContext it's the right size but in the top left. How do I tell it where to draw the view?
-
amit soni over 10 yearshey Casilic thats a great answer!! but i have some doubt like if i have a form which has 40-50 text field and 10-20 text view and user has entered 1000 words in text view then how can i show all text view data
-
casillic over 10 years@amit soni -This method is really for onscreen info only. You probably should generate a report screen from the user's info and have that report converted to PDF. Best of luck.
-
Qing over 9 yearshey see this html2pdf cordova plugin github.com/moderna/cordova-plugin-html2pdf/blob/master/src/ios/… it can print scrollable webview into multipage pdf
-
Jay Mayu over 9 yearsthis crashes in ios 8 at
UIGraphicsEndPDFContext
-
Tom Tallak Solbu about 9 yearsI had the same experience. Got a blank PDF from the first code. Splitting it in two as Alex did, made it work. Can't explain why.
-
David H about 8 yearsYour guard statement means the UIGraphicsEndPDFContext() isn't called - maybe add a defer earlier?
-
Denis Rumiantsev about 8 years@DavidH thanks, David, good idea! Also, I think, there's a good idea add a completion block kind
completion: (success: Bool) -> ()
for guard return cases -
David H about 8 yearsYesterday I posted a Q&A on how to produce a high resolution image by rendering the view in a large image, then drawing the image into a PDF in interested: stackoverflow.com/a/35442187/1633251
-
Ahsan Ebrahim about 8 yearsCan i somehow convert this in PNG or JPG ? because i want to be able to save it in camera roll as well as use in my application. Very nice solution though +1
-
Abha almost 8 years@casillic your code works fine for UIView but I need for UIScrollview. I am using UIScrollview instead of UIView in parameter and using UIScrollview's ContentSize insted of UIView bound. This thing generate PDF but only for visible portion. You have any proper solution for UIScrollview ?
-
Saurabh Prajapati over 6 yearsthis creating PDF for only firstPage! what about scrollview?
-
retrovius over 6 yearsGreat question! I'm not the one to ask, however. Perhaps start another question?
-
Jonas Deichelmann over 6 yearsI've the same problem then @SaurabhPrajapati and I created an Question
-
Hussein about 5 yearsThanks it worked, One question, So I have long scroll view, but the PDF file only shows a portion of it, so is there a way to tweak your code for example to give it Height ?
-
iAleksandr over 4 years@HusseinElbeheiry just use contentView to generate pdf. When I create a scrollView (UIScrollView) I will definitely create a contentView (UIView) and put the contentView in the scrollView, and I add all subsequent elements to the contentView. In this case, it is enough to use contentView to create a PDF document. contentView.exportAsPdfFromView
-
Midhun Narayan almost 3 yearsin iPhone where i can find this file, using files application it is not showing
-
Midhun Narayan almost 3 yearsWhere i can find the saved PDF file?
-
Ashish Chauhan almost 3 years@MidhunNarayan inside your app document directory. Just print the pdfPath on console and access it.
-
Midhun Narayan almost 3 years@AshishChauhan i have printed the path but when i open my file app it is not showing. do i need anything extra to see the converted pdf in my file app