Note : UIWebView to PDF working for me.
Now UIView to PDF is also option but wanted to work with below code as same as used to create PDF in UIWebView.
I have done below code so far for UIView's viewPrintFormatter to be able create PDF:
Added Category of UIPrintPageRenderer for getting PDF Data
#interface UIPrintPageRenderer (PDF)
- (NSData*) printToPDF;
#end
#implementation UIPrintPageRenderer (PDF)
- (NSData*) printToPDF
{
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
Add these define for A4 size
#define kPaperSizeA4 CGSizeMake(595.2,841.8)
Create PDF
UIPrintPageRenderer *render = [[UIPrintPageRenderer alloc] init];
[render addPrintFormatter:self.view.viewPrintFormatter startingAtPageAtIndex:0];
//increase these values according to your requirement
float topPadding = 10.0f;
float bottomPadding = 10.0f;
float leftPadding = 10.0f;
float rightPadding = 10.0f;
CGRect printableRect = CGRectMake(leftPadding,
topPadding,
kPaperSizeA4.width-leftPadding-rightPadding,
kPaperSizeA4.height-topPadding-bottomPadding);
CGRect paperRect = CGRectMake(0, 0, kPaperSizeA4.width, kPaperSizeA4.height);
[render setValue:[NSValue valueWithCGRect:paperRect] forKey:#"paperRect"];
[render setValue:[NSValue valueWithCGRect:printableRect] forKey:#"printableRect"];
NSData *pdfData = [render printToPDF];
if (pdfData) {
[pdfData writeToFile:[NSString stringWithFormat:#"%#/tmp.pdf",NSTemporaryDirectory()] atomically: YES];
}
else
{
NSLog(#"PDF couldnot be created");
}
Related
i want to save pdf to ibook from UIWebView in the app, the html in UIWebView can be multi page.
i try using
NSString *page = [self.lowWebview stringByEvaluatingJavaScriptFromString:#"document.body.outerHTML"];
NSString *path = [self exportHTMLContentToPDF:page];
NSURL *targetURL = [NSURL fileURLWithPath:path];
self.docController = [UIDocumentInteractionController interactionControllerWithURL:targetURL];
if([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:#"itms-books:"]])
{
[self.docController presentOpenInMenuFromRect:CGRectZero inView:self.view animated:YES];
NSLog(#"iBooks installed");
} else {
NSLog(#"iBooks not installed");
}
exportHTMLContentToPDF:
CustomPrintPageRenderer *printPageRenderer = [[CustomPrintPageRenderer alloc] init];
UIMarkupTextPrintFormatter *printFormatter = [[UIMarkupTextPrintFormatter alloc] initWithMarkupText:HTMLContent];
[printPageRenderer addPrintFormatter:printFormatter startingAtPageAtIndex:0];//.addPrintFormatter(printFormatter, startingAtPageAtIndex: 0)
NSData *pdfData = [self drawPDFUsingPrintPageRenderer:printPageRenderer];
NSString *docDirPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *fileName = [docDirPath stringByAppendingPathComponent:#"ticket.pdf"];
[pdfData writeToFile:fileName atomically:true];//.writeToFile(fileName, atomically: true)
NSLog(#"%#", fileName);
return fileName;
the problem is exportHTMLContentToPDF create just one page if UIWebView contain multiple page, and some time the output format is not well print in pdf
thanks in advance.
Create PDF from any Microsoft Document loaded in UIWebview
#define kPaperSizeA4 CGSizeMake(595.2,841.8)
First of all implement UIPrintPageRenderer protocol
#interface UIPrintPageRenderer (PDF)
- (NSData*) printToPDF;
#end
#implementation UIPrintPageRenderer (PDF)
- (NSData*) printToPDF
{
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
Then, call below method after document finished loading in UIWebView
-(void)createPDF:(UIWebView *)webView {
UIPrintPageRenderer *render = [[UIPrintPageRenderer alloc] init];
[render addPrintFormatter:webView.viewPrintFormatter startingAtPageAtIndex:0];
float padding = 10.0f;
CGRect paperRect = CGRectMake(0, 0, kPaperSizeA4.width, kPaperSizeA4.height);
CGRect printableRect = CGRectMake(padding, padding, kPaperSizeA4.width-(padding * 2), kPaperSizeA4.height-(padding * 2));
[render setValue:[NSValue valueWithCGRect:paperRect] forKey:#"paperRect"];
[render setValue:[NSValue valueWithCGRect:printableRect] forKey:#"printableRect"];
NSData *pdfData = [render printToPDF];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
if (pdfData) {
[pdfData writeToFile:directoryPath atomically: YES];
}
else
{
NSLog(#"PDF couldnot be created");
}
});}
Excerpted from PDF Creation in iOS - Create PDF from any Microsoft Document loaded in UIWebview. The original author was Mansi Panchal. Attribution details can be found on the contributor page. The source is licenced under CC BY-SA 3.0 and may be found in the Documentation archive. Reference topic ID: 2416 and example ID: 28437.
#define kPaperSizeA4 CGSizeMake(595.2,841.8)
First of all implement UIPrintPageRenderer protocol
#interface UIPrintPageRenderer (PDF)
- (NSData*) printToPDF;
#end
#implementation UIPrintPageRenderer (PDF)
- (NSData*) printToPDF
{
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
Then, call below method after document finished loading in UIWebView
-(void)createPDF:(UIWebView *)webView {
UIPrintPageRenderer *render = [[UIPrintPageRenderer alloc] init];
[render addPrintFormatter:webView.viewPrintFormatter startingAtPageAtIndex:0];
float padding = 10.0f;
CGRect paperRect = CGRectMake(0, 0, kPaperSizeA4.width, kPaperSizeA4.height);
CGRect printableRect = CGRectMake(padding, padding, kPaperSizeA4.width-(padding * 2), kPaperSizeA4.height-(padding * 2));
[render setValue:[NSValue valueWithCGRect:paperRect] forKey:#"paperRect"];
[render setValue:[NSValue valueWithCGRect:printableRect] forKey:#"printableRect"];
NSData *pdfData = [render printToPDF];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
if (pdfData) {
[pdfData writeToFile:directoryPath atomically: YES];
}
else
{
NSLog(#"PDF couldnot be created");
} });}
Ref: https://medium.com/#javedmultani16/create-pdf-from-any-microsoft-document-loaded-in-uiwebview-in-ios-15229671060b
This may help with quality and multi-page issues :
https://coderwall.com/p/gssuka/rendering-html-pdf-report-for-printing-from-uiwebview
I used web view to load pdf also added an image as subview to my pdfView.
To save the final PDF with subviews,i tried the approach given in the below stack question, it meets the objective but it completely lost quality of the PDF
How to Convert UIView to PDF within iOS?
Now i am try with the below approach,
-(void)savePDFFromWebView:(UIWebView*)webView fileName:(NSString*)_fileName
{
int height, width, header, sidespace;
height = webView.scrollView.contentSize.height;
width = webView.scrollView.contentSize.width;
header = 15;
sidespace = 30;
// set header and footer spaces
UIEdgeInsets pageMargins = UIEdgeInsetsMake(header, sidespace, header, sidespace);
webView.viewPrintFormatter.contentInsets = pageMargins;
UIPrintPageRenderer *renderer = [[UIPrintPageRenderer alloc] init];
[renderer addPrintFormatter:webView.viewPrintFormatter startingAtPageAtIndex:0];
CGSize pageSize = CGSizeMake(width, height);
CGRect printableRect = CGRectMake(pageMargins.left,
pageMargins.top,
pageSize.width - pageMargins.left - pageMargins.right,
pageSize.height - pageMargins.top - pageMargins.bottom);
CGRect paperRect = CGRectMake(0, 0, pageSize.width, pageSize.height);
[renderer setValue:[NSValue valueWithCGRect:paperRect] forKey:#"paperRect"];
[renderer setValue:[NSValue valueWithCGRect:printableRect]
forKey:#"printableRect"];
NSData *pdfData = [self printToPDFWithRenderer:renderer paperRect:paperRect];
// save PDF file
NSString *saveFileName = [NSString stringWithFormat:#"%#%dx%d.pdf",
_fileName, (int)pageSize.width, (int)pageSize.height];
NSString *savePath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)
objectAtIndex:0] stringByAppendingPathComponent:saveFileName];
[pdfData writeToFile: savePath atomically: YES];
}
-(NSData*) printToPDFWithRenderer:(UIPrintPageRenderer*)renderer paperRect:(CGRect)paperRect
{
NSMutableData *pdfData = [NSMutableData data];
UIGraphicsBeginPDFContextToData( pdfData, paperRect, nil );
[renderer prepareForDrawingPages: NSMakeRange(0, renderer.numberOfPages)];
CGRect bounds = UIGraphicsGetPDFContextBounds();
for ( int i = 0 ; i < renderer.numberOfPages ; i++ )
{
UIGraphicsBeginPDFPage();
[renderer drawPageAtIndex: i inRect: bounds];
}
UIGraphicsEndPDFContext();
return pdfData;
}
Here the webView which pass as an input for UIPrintPageRenderer includes the
subviews but the final pdf does not includes subviews.
How to include subviews to save the final PDF?
This question already has answers here:
Creating PDF file from UIWebView
(6 answers)
Closed 5 years ago.
how to create UIWebView Content as pdf file..?
i followed this link but this one not creating the entire webview content(still have some data on webview when i scroll) it is only creating a pdf what the screen is showing..
How to Convert UIView to PDF within iOS?
any help
Use UIPrintPageRenderer from UIWebView Follow below steps :
Add Category of UIPrintPageRenderer for getting PDF Data
#interface UIPrintPageRenderer (PDF)
- (NSData*) printToPDF;
#end
#implementation UIPrintPageRenderer (PDF)
- (NSData*) printToPDF
{
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
Add these define for A4 size
#define kPaperSizeA4 CGSizeMake(595.2,841.8)
Now in UIWebView's webViewDidFinishLoad delegate use UIPrintPageRenderer property of UIWebView.
- (void)webViewDidFinishLoad:(UIWebView *)awebView
{
if (awebView.isLoading)
return;
UIPrintPageRenderer *render = [[UIPrintPageRenderer alloc] init];
[render addPrintFormatter:awebView.viewPrintFormatter startingAtPageAtIndex:0];
//increase these values according to your requirement
float topPadding = 10.0f;
float bottomPadding = 10.0f;
float leftPadding = 10.0f;
float rightPadding = 10.0f;
CGRect printableRect = CGRectMake(leftPadding,
topPadding,
kPaperSizeA4.width-leftPadding-rightPadding,
kPaperSizeA4.height-topPadding-bottomPadding);
CGRect paperRect = CGRectMake(0, 0, kPaperSizeA4.width, kPaperSizeA4.height);
[render setValue:[NSValue valueWithCGRect:paperRect] forKey:#"paperRect"];
[render setValue:[NSValue valueWithCGRect:printableRect] forKey:#"printableRect"];
NSData *pdfData = [render printToPDF];
if (pdfData) {
[pdfData writeToFile:[NSString stringWithFormat:#"%#/tmp.pdf",NSTemporaryDirectory()] atomically: YES];
}
else
{
NSLog(#"PDF couldnot be created");
}
}
You're right, you need a Webview.
If you have the .pdf file in the bundle, simply do this :
#implementation{
UIWebView *documentWebView;
}
- (void)viewDidLoad{ //Or any other method that you want to create the webview with.
//Getting the full screen size
UIWindow* currentWindow = [UIApplication sharedApplication].keyWindow;
CGRect fullScreenRect = currentWindow.bounds;
//Getting the pdf from the bundle ; change filepath with URL if its from the internet
filePath = [[NSBundle mainBundle] pathForResource:#"YourPDFFileName" ofType:#"pdf"];
NSURL *fileURL = [NSURL fileURLWithPath:filePath];
NSURLRequest *request = [NSURLRequest requestWithURL:fileURL];
//Creating the view programatically, because I'm like that.
documentWebView = [[UIWebView alloc] initWithFrame:CGRectMake(fullScreenRect.origin.x, fullScreenRect.origin.y, fullScreenRect.size.width, fullScreenRect.size.height)];
documentWebView.scalesPageToFit = YES;
//Setting a back button to dismiss the view.
UIButton *backButton = [[UIButton alloc]initWithFrame:CGRectMake(fullScreenRect.size.width-115, 10, 100, 30)];
backButton.backgroundColor = [UIColor grayColor];
backButton.alpha = 0.8;
[backButton setTitle:#"Back" forState:UIControlStateNormal];
//Linking the action & the button
[backButton addTarget:self action:#selector(closeWebView:) forControlEvents:UIControlEventTouchUpInside];
//Loading the pdf into the actual view
[documentWebView loadRequest:request];
//Adding the views to the main view
[currentWindow addSubview:documentWebView];
[documentWebView addSubview:backButton];
}
//Dismissing the view
- (IBAction)closeWebView:(id)sender{
[documentWebView removeFromSuperview];
[documentWebView release];
}
I have gone over previous questions touching upon the subject, but A4 Sized PDF is the troublesome part.
The code I have written below saves a proper (proportional) PDF file, but its size (area wise) is 4 times of A4-Size. If I halve the height and width, I get an A4 sized PDF but the content overflows into two pages.
How do I solve the problem? (fundamentally pertaining to scaling)
-(void)savePDFFromWebView:(UIWebView*)webView fileName:(NSString*)_fileName
{
int height, width, header, sidespace;
height = 1754;
width = 1240;
header = 15;
sidespace = 30;
// set header and footer spaces
UIEdgeInsets pageMargins = UIEdgeInsetsMake(header, sidespace, header, sidespace);
webView.viewPrintFormatter.contentInsets = pageMargins;
UIPrintPageRenderer *renderer = [[UIPrintPageRenderer alloc] init];
[renderer addPrintFormatter:webView.viewPrintFormatter startingAtPageAtIndex:0];
CGSize pageSize = CGSizeMake(width, height);
CGRect printableRect = CGRectMake(pageMargins.left,
pageMargins.top,
pageSize.width - pageMargins.left - pageMargins.right,
pageSize.height - pageMargins.top - pageMargins.bottom);
CGRect paperRect = CGRectMake(0, 0, pageSize.width, pageSize.height);
[renderer setValue:[NSValue valueWithCGRect:paperRect] forKey:#"paperRect"];
[renderer setValue:[NSValue valueWithCGRect:printableRect] forKey:#"printableRect"];
NSData *pdfData = [self printToPDFWithRender:renderer paperRect:paperRect];
// save PDF file
NSString *saveFileName = [NSString stringWithFormat:#"%#%dx%d.pdf", _fileName, (int)pageSize.width, (int)pageSize.height];
NSString *savePath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:saveFileName];
[pdfData writeToFile: savePath atomically: YES];
}
- (NSData*) printToPDFWithRenderer:(UIPrintPageRenderer*)renderer paperRect:(CGRect)paperRect
{
NSMutableData *pdfData = [NSMutableData data];
UIGraphicsBeginPDFContextToData( pdfData, paperRect, nil );
[renderer prepareForDrawingPages: NSMakeRange(0, renderer.numberOfPages)];
CGRect bounds = UIGraphicsGetPDFContextBounds();
for ( int i = 0 ; i < renderer.numberOfPages ; i++ )
{
UIGraphicsBeginPDFPage();
[renderer drawPageAtIndex: i inRect: bounds];
}
UIGraphicsEndPDFContext();
return pdfData;
}
Here paperRect you providing is not of A4 size
CGRect paperRect = CGRectMake(0, 0,595.2,841.8);
According printableRect would change
CGRect printableRect = CGRectMake(sidespace,
header,
pageSize.width - (sidespace*2),
pageSize.height - (header*2));
Also I think no need to specify contentInsets as printableRect will do the same. So remove below lines
UIEdgeInsets pageMargins = UIEdgeInsetsMake(header, sidespace, header, sidespace);
webView.viewPrintFormatter.contentInsets = = pageMargins;
I am creating an iPad application, in that i have to use different PDF forms. I got some methods to generate PDF files through code using Quartz2D. But I have to write entire forms through code. I may have to update the PDF forms in future, so again I have to write the code. So I heard that there is a component called iTextSharp for .net pdf creation - is there something similar for iOS? So that I can use some XML templates to create the PDF files.
Please help, thanks
I do this in my app using the iOS print subsystem and the UIMarkupTextPrintFormatter. The trick is to write your own custom UIPrintPageRenderer that overrides and returns correct values from paperRect and numberOfPages. You'll add your UIMarkupTextPrintFormatter(s) to your custom UIPrintPageRenderer.
Then, you'll need routines similar to this, in the context of your custom UIPrintPageRenderer:
- (CGRect) paperRect
{
if (!_generatingPdf)
return [super paperRect];
return UIGraphicsGetPDFContextBounds();
}
- (CGRect) printableRect
{
if (!_generatingPdf)
return [super printableRect];
return CGRectInset( self.paperRect, 20, 20 );
}
- (NSData*) printToPDF
{
_generatingPdf = YES;
NSMutableData *pdfData = [NSMutableData data];
UIGraphicsBeginPDFContextToData( pdfData, CGRectMake(0, 0, 792, 612), nil ); // letter-size, landscape
[self prepareForDrawingPages: NSMakeRange(0, 1)];
CGRect bounds = UIGraphicsGetPDFContextBounds();
for ( int i = 0 ; i < self.numberOfPages ; i++ )
{
UIGraphicsBeginPDFPage();
[self drawPageAtIndex: i inRect: bounds];
}
UIGraphicsEndPDFContext();
_generatingPdf = NO;
// NSString* filename = #"/Volumes/Macintosh HD 2/test.pdf";
// [pdfData writeToFile: filename atomically: YES];
return pdfData;
}
#TomSwift : agree with his answer but i would like to explain in better way
To be able create PDF from UIWebView is load HTML to yourWebView or there might be case yourWebView can also be hidden to generate PDF but process remains the same
1) Added Category of UIPrintPageRenderer for getting PDF Data as yourWebView.viewPrintFormatter need to be used
#interface UIPrintPageRenderer (PDF)
- (NSData*) printToPDF;
#end
#implementation UIPrintPageRenderer (PDF)
- (NSData*) printToPDF
{
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
2) Add these define for A4 size or any custom size you want
#define kPaperSizeA4 CGSizeMake(595.2,841.8)
3) Process how we can create PDF
//create print renderer
UIPrintPageRenderer *render = [[UIPrintPageRenderer alloc] init];
[render addPrintFormatter:yourWebView.viewPrintFormatter startingAtPageAtIndex:0];
//provide padding ---- increase these values according to your requirement
float topPadding = 10.0f;
float bottomPadding = 10.0f;
float leftPadding = 10.0f;
float rightPadding = 10.0f;
//provide rect for printing and for actual PDF Rect of page
CGRect printableRect = CGRectMake(leftPadding,
topPadding,
kPaperSizeA4.width-leftPadding-rightPadding,
kPaperSizeA4.height-topPadding-bottomPadding);
CGRect paperRect = CGRectMake(0, 0, kPaperSizeA4.width, kPaperSizeA4.height);
[render setValue:[NSValue valueWithCGRect:paperRect] forKey:#"paperRect"];
[render setValue:[NSValue valueWithCGRect:printableRect] forKey:#"printableRect"];
//category created above is used here
NSData *pdfData = [render printToPDF];
//Save PDF to directory for usage
if (pdfData) {
[pdfData writeToFile:[NSString stringWithFormat:#"%#/tmp.pdf",NSTemporaryDirectory()] atomically: YES];
}
else
{
NSLog(#"PDF couldnot be created");
}