How to generate PDF without page break - ios

I'm converting my WebView to PDf using following code.
UIWebView *webView = self.webView;
NSString *heightStr = [webView stringByEvaluatingJavaScriptFromString:#"document.body.scrollHeight;"];
int height = [heightStr intValue];
// CGRect screenRect = [[UIScreen mainScreen] bounds];
// CGFloat screenHeight = (self.contentWebView.hidden)?screenRect.size.width:screenRect.size.height;
CGFloat screenHeight = webView.bounds.size.height;
int pages = ceil(height / screenHeight);
NSMutableData *pdfData = [NSMutableData data];
UIGraphicsBeginPDFContextToData(pdfData, webView.bounds, nil);
CGRect frame = [webView frame];
for (int i = 0; i < pages; i++) {
// Check to screenHeight if page draws more than the height of the UIWebView
if ((i+1) * screenHeight > height) {
CGRect f = [webView frame];
f.size.height -= (((i+1) * screenHeight) - height);
f.size.width = self.webView.bounds.size.width*1.6;
[webView setFrame: f];
}
UIGraphicsBeginPDFPage();
CGContextRef currentContext = UIGraphicsGetCurrentContext();
// CGContextTranslateCTM(currentContext, 72, 72); // Translate for 1" margins
[[[webView subviews] lastObject] setContentOffset:CGPointMake(0, screenHeight * i) animated:NO];
[webView.layer renderInContext:currentContext];
}
UIGraphicsEndPDFContext();
// Retrieves the document directories from the iOS device
NSArray* documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
NSString* documentDirectory = [documentDirectories objectAtIndex:0];
NSString* documentDirectoryFilename =[documentDirectory stringByAppendingString:#"/pdfFile.PDF"] ;
// instructs the mutable data object to write its context to a file on disk
[pdfData writeToFile:documentDirectoryFilename atomically:YES];
[webView setFrame:frame];
But the issue is its generating PDF with page break as shown in image.
I don't want this page break.can any one suggest what should I do.

You are setting the page size here
UIGraphicsBeginPDFContextToData(pdfData, webView.bounds, nil);
currently set to webView.bounds
Change it with appropriate value.

This little css worked for me.
#media print {
.avoid_pagebreak { display: block; page-break-inside:avoid; page-break-before: auto; }
}
...
<div class="avoid_pagebreak">
...
</div>

Related

Xcode - Get file from NSDocumentDirectory path

I generated a multi page pdf from my web view and I would like to share the pdf file via an ActivityViewController. I only have the file path and dont know, how to access the file to let them share via the ActivityViewController.
CGRect origframe = webView.frame;
NSString *heightStr = [webView stringByEvaluatingJavaScriptFromString:#"document.body.scrollHeight;"]; // Get the height of our webView
int height = [heightStr intValue];
// Size of the view in the pdf page
CGFloat maxHeight = 568;
CGFloat maxWidth = webView.frame.size.width;
int pages = ceil(height / maxHeight);
// gets the total no:of pages needed in PDF
[webView setFrame:CGRectMake(0.f, 0.f, maxWidth, maxHeight)];
NSArray* documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
NSString* documentDirectory = [documentDirectories objectAtIndex:0];
NSString *pdfFileName = [documentDirectory stringByAppendingPathComponent:#"mypdf.pdf"];
UIGraphicsBeginPDFContextToFile(pdfFileName, CGRectZero, nil);
int i = 0;
for ( ; i < pages; i++)
{
if (maxHeight * (i+1) > height)
{ // Check to see if page draws more than the height of the UIWebView
CGRect f = [webView frame];
f.size.height -= (((i+1) * maxHeight) - height);
[webView setFrame: f];
}
// Specify the size of the pdf page
CGRect PDFRect = CGRectMake(0, 0, webView.frame.size.width, webView.frame.size.height);
UIGraphicsBeginPDFPageWithInfo(PDFRect, nil);
CGContextRef currentContext = UIGraphicsGetCurrentContext();
// Move the context for the margins
CGContextScaleCTM(currentContext, 1, 1);
// offset the webview content so we're drawing the part of the webview for the current page
[[[webView subviews] lastObject] setContentOffset:CGPointMake(0, maxHeight * i) animated:NO];
// draw the layer to the pdf, ignore the "renderInContext not found" warning.
[webView.layer renderInContext:currentContext];
}
// all done with making the pdf
UIGraphicsEndPDFContext();
// Restore the webview and move it to the top.
[webView setFrame:origframe];
[[[webView subviews] lastObject] setContentOffset:CGPointMake(0, 0) animated:NO];
How can I share the finished file?
Thanks in advance!
You should put you file url into UIActivityViewController
NSString * title =[NSString stringWithFormat:#"Some title string", pdfFileName];
NSArray* pdfToShare = #[title];
UIActivityViewController* activityViewController =[[UIActivityViewController alloc] initWithActivityItems:pdfToShare applicationActivities:nil];
[self presentViewController:activityViewController animated:YES completion:^{}];
UPDATE:
https://developer.apple.com/documentation/foundation/nsdata/1547245-datawithcontentsofurl
NSError* error = nil;
NSData* data = [NSData dataWithContentsOfURL: pdfFileName options:NSDataReadingUncached error:&error];
if (error) {
NSLog(#"%#", [error localizedDescription]);
} else {
// make some stuff with pdf data
}

Get PDF document height in iOS WebView

I am try to display a PDF in UIWebView via NSURL. It works fine.
But I do not know the height of pdf document. So sometimes it creates blank space or need to scroll. The PDF may also contain multiple pages.
I only want to show first page if it contain multi pages.
My code is as follow:
NSURL *url = [NSURL URLWithString:#"http://www.eecs.harvard.edu/econcs/pubs/online.pdf"];
NSURLRequest * request = [NSURLRequest requestWithURL:url];
[web_large loadRequest:request];
[web_large setScalesPageToFit:YES];
Right now, the WebView has a fixed height
Pradumna Patil's answer is correct. I combined your code with his, and it worked fine. Just paste the following lines into your project and see for yourself:
UIWebView *web_large = [[UIWebView alloc]init];
[self.view addSubview:web_large];
NSURL *url = [NSURL URLWithString:#"https://www.truthinadvertising.org/wp-content/uploads/2014/09/App-Store-Review-Guidelines.pdf"];
NSURLRequest * request = [NSURLRequest requestWithURL:url];
[web_large loadRequest:request];
[web_large setScalesPageToFit:YES];
CGPDFDocumentRef pdfDocumentRef = CGPDFDocumentCreateWithURL((CFURLRef)url);
CGPDFPageRef pdfPageRef = CGPDFDocumentGetPage(pdfDocumentRef, 1);
CGRect pdfPageRect = CGPDFPageGetBoxRect(pdfPageRef, kCGPDFMediaBox);
float width = pdfPageRect.size.width;
float height = pdfPageRect.size.height;
CGRect screenRect = [[UIScreen mainScreen]bounds];
web_large.frame = CGRectMake(0, 0, screenRect.size.width, height*screenRect.size.width/width);
Try this
There is this method:
size_t CGPDFDocumentGetNumberOfPages(CGPDFDocumentRef document)
That gives you the number of pages.
For ex.
NSURL *pdfUrl = [NSURL fileURLWithPath:yourPath];
CGPDFDocumentRef document = CGPDFDocumentCreateWithURL((CFURLRef)pdfUrl);
Below code gives height of single page in pdf file
float width = CGPDFPageGetBoxRect(pdfPageRef, kCGPDFMediaBox).size.width;
float height = CGPDFPageGetBoxRect(pdfPageRef, kCGPDFMediaBox).size.height;
Hope it helps.
in Swift you can do:
let documents = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first
let writePath = documents?.appending("/myPdf.pdf")
let pdf: CGPDFDocument! = CGPDFDocument(URL.init(fileURLWithPath: writePath!) as CFURL)`enter code here`
let firstPage: CGPDFPage = pdf.page(at: 1)!
let heightFirstPage :CGRect = firstPage.getBoxRect(.mediaBox)
var heightPagePdf : CGFloat = heightFirstPage.height;
the variable 'pdf' also has a property 'numberOfPages', so you can know the entire height of pdf document (pdf.numberOfPages * heightPagePdf).
best regard
This one is easy.
You have to access the scrollview of the webView not the webview itself:
CGFloat totalHeight = self.webView.scrollView.contentSize.height;
Try this .. Its working fine
NSURL* pdfFileUrl = targetURL;
CGPDFDocumentRef pdf = CGPDFDocumentCreateWithURL((CFURLRef)pdfFileUrl);
CGFloat pdfHeight = 0;
NSUInteger totalNum = CGPDFDocumentGetNumberOfPages(pdf);
for(int i = 0; i < totalNum; i++ ) {
CGPDFPageRef myPageRef=CGPDFDocumentGetPage(pdf, i+1);
CGRect cropBox = CGPDFPageGetBoxRect(myPageRef, kCGPDFCropBox);
pdfHeight+=cropBox.size.height;
int pageRotation = CGPDFPageGetRotationAngle(myPageRef);
CGSize pageVisibleSize = CGSizeMake(cropBox.size.width, cropBox.size.height);
if ((pageRotation == 90) || (pageRotation == 270) ||(pageRotation == -90)) {
pageVisibleSize = CGSizeMake(cropBox.size.height, cropBox.size.width);
}
}
NSLog(#"%f",pdfHeight);
Instead of loading pdf in webView I would like to suggest you to draw PDF in UIView, Like I have done in my own project and it's working perfect.
Below is mine UIView subClass which draw pdf in UIView context.
PDFPage.h
#import <UIKit/UIKit.h>
#protocol PDFPageDelegate;
#interface PDFPage : UIView
#property uint currentPage;
#property unsigned long totalPages;
#property CGRect pageRect;
#property NSString *pdfPath;
#property id<PDFPageDelegate> delegate;
- (CGRect)setPdf:(NSString*)filePath;
- (void)swipeLeft;
- (void)swipeRight;
- (void)setPageNumber:(NSUInteger )targetPageNumber;
#end
#protocol PDFPageDelegate <NSObject>
- (void)pdfWillSwipeToLeft:(uint)upcommingPageNumber;
- (void)pdfWillSwipeToRight:(uint)upcommingPageNumber;
- (void)pdfTaped:(CGPoint)tapAt;
- (void)pdfDoubleTapped;
#end
PDFPage.m
#import "PDFPage.h"
#implementation PDFPage
#synthesize pageRect = _pageRect;
#synthesize currentPage = _currentPage;
#synthesize totalPages = _totalPages;
#synthesize delegate = _delegate;
#synthesize pdfPath = _pdfPath;
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {}
_currentPage = 1;
UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeLeft)];
swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
[self addGestureRecognizer:swipeLeft];
UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeRight)];
swipeRight.direction = UISwipeGestureRecognizerDirectionRight;
[self addGestureRecognizer:swipeRight];
return self;
}
- (void)setPageNumber:(NSUInteger )targetPageNumber
{
_currentPage = (uint)targetPageNumber;
[self setNeedsDisplay];
[UIView transitionWithView:self duration:0.5
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
[self.layer displayIfNeeded];
} completion:nil];
}
- (void)swipeLeft
{
if(_currentPage == _totalPages)
return;
_currentPage++;
[_delegate pdfWillSwipeToLeft:_currentPage];
[self setNeedsDisplay];
[UIView transitionWithView:self duration:0.5
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
[self.layer displayIfNeeded];
} completion:nil];
}
- (void)swipeRight
{
if(_currentPage == 1)
return;
_currentPage--;
[_delegate pdfWillSwipeToRight:_currentPage];
[self setNeedsDisplay];
[UIView transitionWithView:self duration:0.5
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
[self.layer displayIfNeeded];
} completion:nil];
}
- (void)drawRect:(CGRect)rect
{
CGContextRef ctx = UIGraphicsGetCurrentContext();
// PDF might be transparent, assume white paper
[[UIColor whiteColor] set];
CGContextFillRect(ctx, rect);
// Flip coordinates
CGContextGetCTM(ctx);
CGContextScaleCTM(ctx, 1, -1);
CGContextTranslateCTM(ctx, 0, -rect.size.height);
// url is a file URL
CFURLRef pdfURL = (__bridge CFURLRef)[NSURL fileURLWithPath:_pdfPath];
CGPDFDocumentRef pdf = CGPDFDocumentCreateWithURL(pdfURL);
CGPDFPageRef page1 = CGPDFDocumentGetPage(pdf, _currentPage);
// get the rectangle of the cropped inside
CGRect mediaRect = CGPDFPageGetBoxRect(page1, kCGPDFCropBox);
CGContextScaleCTM(ctx, rect.size.width / mediaRect.size.width,
rect.size.height / mediaRect.size.height);
CGContextTranslateCTM(ctx, -mediaRect.origin.x, -mediaRect.origin.y);
// draw it
CGContextDrawPDFPage(ctx, page1);
CGPDFDocumentRelease(pdf);
}
- (CGRect)setPdf:(NSString*)filePath
{
_pdfPath =filePath;
_currentPage = 1;
CFURLRef pdfURL = (__bridge CFURLRef)[NSURL fileURLWithPath:_pdfPath];
CGPDFDocumentRef pdf = CGPDFDocumentCreateWithURL(pdfURL);
CGPDFPageRef page = CGPDFDocumentGetPage(pdf,_currentPage);
_pageRect = CGPDFPageGetBoxRect(page, kCGPDFCropBox);
_totalPages = (CGPDFDocumentGetNumberOfPages(pdf));
[self setNeedsDisplay];
[UIView transitionWithView:self duration:0.5
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
[self setNeedsDisplay];
} completion:nil];
CGRect finalRect = CGRectMake(0, 0, _pageRect.size.width, _pageRect.size.height);
return finalRect;
}
How to use:-
NSData *pdfData = [NSData dataWithContentsOfURL:[NSURL URLWithString:pdfPath]]; // here pdfPath is webURL
NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString * savePDFAt = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
savePDFAt = [NSString stringWithFormat:#"%#/PDFs/",savePDFAt];
[[NSFileManager defaultManager] createDirectoryAtPath:savePDFAt withIntermediateDirectories:NO attributes:nil error:nil];
[savePDFAt stringByAppendingPathComponent:"test.pdf"];
if([pdfData writeToFile:savePDFAt options:0 error:&error])
NSLog(#"PDF download complete");
PDFPage *pdfPage = [PDFPage new];
pdfPage.alpha = 0.0f;
pdfPage.delegate = self;
pdfPage.frame = [pdfPage setPdf:pdfPath];
Then add this pdfPage to self's view or to scroller.

Create PDF from UIWebview fails to include subviews in the final PDF

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?

Issues in generating PDF from uiwebview in objective c

I have open pdf file in uiwebview, add image and text in uiwebview subview.Then i tried created pdf file. Below sample i have used to generate pdf file. Multiple page writing in single page. How can i write sample quality and exact size.
Please check screen shots and below source
UIGraphicsBeginPDFContextToData( pdfData, CGRectZero, nil );
for (int i = 0; i < 10; i++) {
CGRect f = [pdfView frame];
[pdfView setFrame: f];
UIGraphicsBeginPDFPage();
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(currentContext, 72, 72); // Translate for 1" margins
[[[pdfView subviews] lastObject] setContentOffset:CGPointMake(0, 648 * i) animated:NO];
[pdfView.layer renderInContext:currentContext];
}
UIGraphicsEndPDFContext();
and also i have tried this following link but i couldn't add uiwebview subview to write the pdf.
http://b2cloud.com.au/tutorial/drawing-over-a-pdf-in-ios-pdf-template/
You can use the following category on UIView to create a PDF file:
#import <QuartzCore/QuartzCore.h>
#implementation UIView(PDFWritingAdditions)
- (void)renderInPDFFile:(NSString*)path
{
CGRect mediaBox = self.bounds;
CGContextRef ctx = CGPDFContextCreateWithURL((CFURLRef)[NSURL fileURLWithPath:path], &mediaBox, NULL);
CGPDFContextBeginPage(ctx, NULL);
CGContextScaleCTM(ctx, 1, -1);
CGContextTranslateCTM(ctx, 0, -mediaBox.size.height);
[self.layer renderInContext:ctx];
CGPDFContextEndPage(ctx);
CFRelease(ctx);
}
#end
Bad news: UIWebView does not create nice shapes and text in the PDF, but renders itself as an image into the PDF.
OR
How to Convert UIView to PDF within iOS?
OR
Creating PDF file from UIWebView
This might helps you :)
I have also used the same its working fine Hope this will be helpful for you.
Create a block:-
typedef void (^PdfCompletion)(BOOL status,NSString *filePath,NSArray *fbArr);
-(void)addData
{
[MBProgressHUD showHUDAddedTo:self.view animated:YES];
NSMutableDictionary *contactDict = [[NSMutableDictionary alloc] init];
[contactDict setObject:contactTextField.text forKey:#"phonenumber"];
[contactDict setObject:emailTextField.text forKey:#"emailid"];
[contactDict setObject:userNameLabel.text forKey:#"displayname"];
[self drawPdf:contactDict completion:^(BOOL status,NSString *filePath,NSArray *fbArr)
{
if (status)
{
NSMutableArray *arr;
arr = [[NSMutableArray alloc] init];
NSData *filedata;
filedata = [NSData dataWithContentsOfFile:filePath];
double locaTotalFileSize = filedata.length +498;
totalFileSize += locaTotalFileSize;
NSMutableDictionary *fileDict = [[NSMutableDictionary alloc] init];
[fileDict setObject:userPicImageView.image forKey:#"image"];
[fileDict setObject:filePath forKey:#"filePath"];
[fileDict setObject:#"txt" forKey:#"fileType"];
[fileDict setObject:[NSString stringWithFormat:#"%#_%#_%#",#"contact",[self getFbID],[self CurrentSystemTime]] forKey:#"fileName"];
[fileDict setObject:#"1" forKey:#"uploadStatus"];
[fileDict setObject:#"0 KB/0 KB" forKey:#"fileSizeStatus"];
[fileDict setObject:#"0 KB/0 KB" forKey:#"ContentSize"];
[arr addObject:fileDict];
[self switchToReviewFiles:arr];
//////NSLog(#"pdf convrt successfull");
}
else
{
//////NSLog(#"Error to convert into pdf");
}
}];
}
// Then Call The DrawPDF Method::--
-(void)drawPdf:(NSMutableDictionary *)drawText completion:(PdfCompletion)callback
{
NSString* fileName = #"contact_card.txt";
NSArray *arrayPaths =
NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory,
NSUserDomainMask,
YES);
NSString *path = [arrayPaths objectAtIndex:0];
NSString* txtFileName = [path stringByAppendingPathComponent:fileName];
NSData *data = [NSJSONSerialization dataWithJSONObject:drawText options:NSJSONWritingPrettyPrinted error:nil];
[data writeToFile:txtFileName atomically:YES];
callback(YES,txtFileName,nil);
}
It looks to me like you're just trying to add content to an existing PDF, right?
- (void) drawCustomPDFContent
{
// Put your drawing calls here
// Draw a red box
[[UIColor redColor] set];
UIRectFill(CGRectMake(20, 20, 100, 100));
// Example of drawing your view into PDF, note that this will be a rasterized bitmap, including the text.
// To get smoother text you'll need to use the NSString draw methods
CGContextRef ctx = UIGraphicsGetCurrentContext();
[view.layer renderInContext:ctx];
}
- (void) createCustomPDF
{
NSURL* pdfURL = ... /* URL to pdf file */;
CGPDFDocumentRef pdf = CGPDFDocumentCreateWithURL((CFURLRef)pdfURL);
const size_t numberOfPages = CGPDFDocumentGetNumberOfPages(pdf);
NSMutableData* data = [NSMutableData data];
UIGraphicsBeginPDFContextToData(data, CGRectZero, nil);
for(size_t page = 1; page <= numberOfPages; page++)
{
// Get the current page and page frame
CGPDFPageRef pdfPage = CGPDFDocumentGetPage(pdf, page);
const CGRect pageFrame = CGPDFPageGetBoxRect(pdfPage, kCGPDFMediaBox);
UIGraphicsBeginPDFPageWithInfo(pageFrame, nil);
// Draw the page (flipped)
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSaveGState(ctx);
CGContextScaleCTM(ctx, 1, -1);
CGContextTranslateCTM(ctx, 0, -pageFrame.size.height);
CGContextDrawPDFPage(ctx, pdfPage);
CGContextRestoreGState(ctx);
if(page == 1)
{
[self drawCustomPDFContent];
}
}
UIGraphicsEndPDFContext();
CGPDFDocumentRelease(pdf);
pdf = nil;
// Do something with data here
[data writeToFile:... atomically:YES];
}
Parts referenced from:
http://b2cloud.com.au/tutorial/drawing-over-a-pdf-in-ios-pdf-template/
You can try this.It worked for me :)
https://github.com/iclems/iOS-htmltopdf/blob/master/NDHTMLtoPDF.h
NSString *html = [webView stringByEvaluatingJavaScriptFromString:#"document.documentElement.outerHTML"];
self.PDFCreator = [NDHTMLtoPDF createPDFWithHTML:html
pathForPDF:[path stringByExpandingTildeInPath]
delegate:self
pageSize:CGSizeMake(595,847)
margins:UIEdgeInsetsMake(105, 0, 0, 0)];
Pass the webView like this
You are actually very close with the code you have. I have a feeling your biggest problem is grabbing a new CGContextRef with each loop iteration..
UIGraphicsBeginPDFContextToData( pdfData, CGRectZero, nil );
CGContextRef currentContext = UIGraphicsGetCurrentContext();//movedByJef
// default pdf..
// 8.5 X 11 inch
// 612 x 792
for (int i = 0; i < 10; i++) {
CGContextSaveGstate( currentContext ); //addedByJef
CGRect f = [pdfView frame];
[pdfView setFrame: f]; // hmm what does this even do??
UIGraphicsBeginPDFPage();
CGContextTranslateCTM(currentContext, -72, -72); // Translate for 1" margins ///editedByJef, you had it backwards..
//assuming you want a 72pt margin on right and bottom as well..
//we want to reduce our size (612 x 792) by 72pts on all four sides..
CGSize printPageSize = CGSizeMake( (612.0 - (72.0 * 2.0)), (792.0 -(72.0*2.0)) );
CGSize layrSize = self.layer.bounds.size;
//so we translate the context so our view fills it nicely..
CGFloat xScaler = layrSize.width / printPageSize.width;
CGFloat yScaler = layrSize.height / printPageSize.height;
CGContextConcatCTM(currentContext, CGAffineTransformMakeScale(xScaler, yScaler) );
[[[pdfView subviews] lastObject] setContentOffset:CGPointMake(0, 648 * i) animated:NO];
[pdfView.layer renderInContext:currentContext];
CGContextRestoreGstate(currentContext);//added by jef
}
UIGraphicsEndPDFContext();
let me know how you go with that, There will undoubtedly be a bit of shuffling in the order of the transforms, maybe a translate needed either side of the scaling, but this should get you really close..

Save UIWebView content as A4 sized PDF

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;

Resources