I have done this in the past using UIPrintPageRenderer. This is a more realistic way to create a PDF file from UIWebView, and it has been working for me so far. I tested this solution with Xcode 6 and iOS 8.2. In addition, I tried to print the resulting PDF file and everything printed fine.
When I read the OP, I did some testing with different page sizes to find out if I could get an empty PDF file. There are several key elements that I have identified that can contribute to an empty PDF file. I identified them in the code.
When you call webViewDidFinishLoad (), the view may not load 100%. A check is needed to see if viewing continues. This is important as it may be the source of your problem. If this is not so, then we will be happy. It is very important to note here. Some web pages load dynamically (defined on the page itself). Take, for example, youtube.com. The page is displayed almost immediately, with a loading screen. This will trick our webview, and its isLoading property will be set to false, while the webpage is still loading content dynamically. However, this is a fairly rare case, and in general, this solution will work well. If you need to create a PDF file from such a dynamic download page, you may need to move the actual generation to another location. Even with a dynamic loading web page, you will get a PDF file showing the loading screen, and not an empty PDF file.
Another key aspect is setting printableRect and pageRect. Please note that they are installed separately. If the printableRect value is less than paperRect, you will get some addition to the content - see, For example, the code. Here is the link in the Apple APIs document with some brief descriptions for both.
The sample code below adds a category to the UIPrintPageRenderer to create the actual PDF data. The code in this example was compiled using various resources on the Internet in the past, and I could not find which ones were used for proper lending.
@interface UIPrintPageRenderer (PDF) - (NSData*) createPDF; @end @implementation UIPrintPageRenderer (PDF) - (NSData*) createPDF { NSMutableData *pdfData = [NSMutableData data]; UIGraphicsBeginPDFContextToData( pdfData, self.paperRect, nil ); [self prepareForDrawingPages: NSMakeRange(0, self.numberOfPages)]; CGRect bounds = UIGraphicsGetPDFContextBounds(); for ( int i = 0 ; i < self.numberOfPages ; i++ ) { UIGraphicsBeginPDFPage(); [self drawPageAtIndex: i inRect: bounds]; } UIGraphicsEndPDFContext(); return pdfData; } @end
And here is what I have in webViewDidFinishLoad ()
- (void)webViewDidFinishLoad:(UIWebView *)webViewIn { NSLog(@"web view did finish loading"); // webViewDidFinishLoad() could get called multiple times before // the page is 100% loaded. That why we check if the page is still loading if (webViewIn.isLoading) return; UIPrintPageRenderer *render = [[UIPrintPageRenderer alloc] init]; [render addPrintFormatter:webViewIn.viewPrintFormatter startingAtPageAtIndex:0]; // Padding is desirable, but optional float padding = 10.0f; // Define the printableRect and paperRect // If the printableRect defines the printable area of the page CGRect paperRect = CGRectMake(0, 0, PDFSize.width, PDFSize.height); CGRect printableRect = CGRectMake(padding, padding, PDFSize.width-(padding * 2), PDFSize.height-(padding * 2)); [render setValue:[NSValue valueWithCGRect:paperRect] forKey:@"paperRect"]; [render setValue:[NSValue valueWithCGRect:printableRect] forKey:@"printableRect"]; // Call the printToPDF helper method that will do the actual PDF creation using values set above NSData *pdfData = [render createPDF]; // Save the PDF to a file, if creating one is successful if (pdfData) { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *path = [paths objectAtIndex:0]; NSString *pdfPath = [path stringByAppendingPathComponent:[NSString stringWithFormat:@"Purchase Order.pdf"]]; [pdfData writeToFile:pdfPath atomically:YES]; } else { NSLog(@"error creating PDF"); } }
PDFSize is defined as a constant defined by the standard A4 page size. It can be edited according to your needs.
#define PDFSize CGSizeMake(595.2,841.8)