PDF Generation using UIPrintPageRenderer

AirPrint enabled printers accept PDF files and UIPrintPageRenderer prints that content to PDF file. Hence UIPrintPageRenderer can draw to PDF context though there are none public API provided to use this functionality. In this post we will explore this possibility.

There are several StackOverFlow question which talk about how to use private API to achieve pdf generation utilizing UIPrintPageRenderer:

Is there any way to generate PDF file from a XML/HTML template in iOs
Generating a PDF using the new printing stuff in iOS 4.2
How to pretend to be a Printer on iOS like the Apps Save2PDF or AdobeĀ® CreatePDF?

In this post we have employed the methods explained in above stack overflow questions. Following steps lead to PDf generation from simple text, html or a view:

1) Create a Print Formatter: This is basically the content you want to generate PDF with. A print formatter can be an instance of UISimpleTextPrintFormatter, UIMarkupTextPrintFormatter, or UIViewPrintFormatter. These allow to create pdf with simple text, html or a view respectively.

NSString *html = @”<b>Hello <i>World!</i></b>”;

UIMarkupTextPrintFormatter *fmt = [[UIMarkupTextPrintFormatter alloc] initWithMarkupText:html];

2) Assign print formatter to UIPrintPageRenderer: Once you have created your print formatter add it to UIPrintPageRenderer at proper index. Method addPrintFormatter:startingAtPageAtIndex: allows any print formatter to be added. One has to pass appropriate index as well.

UIPrintPageRenderer *render = [[UIPrintPageRenderer alloc] init];

[render addPrintFormatter:fmt startingAtPageAtIndex:0];

3) Assign paperRect and printableRect: There is no public API to assign these values hence we need to use setValue:forKey: to assign these values. First we calculate the proper CGRect for these values and then use setValue:forKey: to assign these.

CGRect page;

page.origin.x=0;

page.origin.y=0;

page.size.width=792;

page.size.height=612;

CGRect printable=CGRectInset( page, 0, 0 );

[render setValue:[NSValue valueWithCGRect:page] forKey:@”paperRect”];

[render setValue:[NSValue valueWithCGRect:printable] forKey:@”printableRect”];

4) Create PDF Context and draw: Now we create PDF context UIGraphicsBeginPDFContextToData and draw using UIPrintPageRenderer.

NSMutableData * pdfData = [NSMutableData data];

UIGraphicsBeginPDFContextToData( pdfData, CGRectZero, nil );

for (NSInteger i=0; i < [render numberOfPages]; i++)

{

UIGraphicsBeginPDFPage();

CGRect bounds = UIGraphicsGetPDFContextBounds();

[render drawPageAtIndex:i inRect:bounds];

}

UIGraphicsEndPDFContext();

5) Save PDF file:Once the drawing is complete we can save this in a file in documents directory.

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

NSString *documentsDirectory = [paths objectAtIndex:0];

NSString * pdfFile = [[documentsDirectory stringByAppendingPathComponent:@"test.pdf"] retain];

[pdfData writeToFile:pdfFile atomically:YES];

Source code to generate PDF using UIPrintPageRenderer.

 

 

  1. how can we set the value to print powerpoint (ppt) file? I have tried to set CGRect but I don’t get full size. I got with white space on paper.

  2. Hi, I am David. I am using your files to create multiple PDF files of HTML files. It works very nicely, but There is one bug I can not fix. When I create PDF file out of a HTML site with 1001 Images (QR Codes), approximately 50 PDF files, the app crashes and gives me the error: ImageDiskCach: Couldn’t find old Path. I think the error is because you use a UIWebView. Is there a way to fix this, or is there a work around, I can’t find any working solution. Another question is what dpi are the PDF files, I need this to convert px to mm, I cant find any hard coded value. Please send me an email at me [ at ] idoodler . de.

    Thanks for your great work.

    • The crash could be because of the memory issues. You can try to see if it depends on the number of images.

      For dpi you may want to look at following code:

      page.origin.x=0;
      page.origin.y=0;
      page.size.width=792;
      page.size.height=612;

      in createPDF: method.

  3. Hi,

    Thanks for the code. It works great !
    I’m generating an HTML code including a section that I want to be repeated in every page. So I use that works fine in the HTML (safari, chrome, IE), however in the pdf that is created it doesn’t repeat.

    Is there a way to implement this ?

    Thanks !
    Eddie

Leave a Comment


NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>