I'm having trouble breaking my PDF out into multiple pages from a single UIView. I'm trying to keep this as simple as possible. I have a UIScrollView that can vary in height. As of right now, I can get the first page to display correctly, but nothing after that. I'm pretty stumped at this point. Here's what I have:
NSMutableData *pdfData = [NSMutableData data];
UIGraphicsBeginPDFContextToData(pdfData, CGRectZero, nil);
CGContextRef pdfContext = UIGraphicsGetCurrentContext();
NSInteger pageHeight = 867;
for (int originY = 0; originY < self.scrollView.contentSize.height; originY += pageHeight) {
// Start a new page.
UIGraphicsBeginPDFPageWithInfo(CGRectMake(0,originY,768,pageHeight), nil);
[self.scrollView.layer renderInContext:pdfContext];
for (UIView *subview in self.scrollView.subviews) {
[subview.layer renderInContext:pdfContext];
}
}
UIGraphicsEndPDFContext();
I'm trying to traverse this single UIScrollView and pick out the "pages" based on this frame, but that's not exactly working. Any help would be appreciated. I have read the apple docs on this topic and had problems translating that into my own application.
This worked pretty well for me. Make your life easier and just call on CGContextTranslateCTM.
NSInteger pageHeight = 792; // Standard page height - adjust as needed
NSInteger pageWidth = 612; // Standard page width - adjust as needed
/* CREATE PDF */
NSMutableData *pdfData = [NSMutableData data];
UIGraphicsBeginPDFContextToData(pdfData, CGRectMake(0,0,pageWidth,pageHeight), nil);
CGContextRef pdfContext = UIGraphicsGetCurrentContext();
for (int page=0; pageHeight * page < scrollView.frame.size.height; page++)
{
UIGraphicsBeginPDFPage();
CGContextTranslateCTM(pdfContext, 0, -pageHeight * page);
[scrollView.layer renderInContext:pdfContext];
}
UIGraphicsEndPDFContext();
Related
I have this method here that takes my UIWebView and convert into a PDF and its working well. But when I print off this PDF or email it, its cut off. Its like its only generating what the size of the UIWebView that I set (which is width: 688 & height: 577) If I increase the size of the UIWebView to lets say 900 or 1024 my PDF is empty. My UIWebView is bigger than 577, but in my app, I am able to scroll.
Here is method....
-(void)webViewDidFinishLoad:(UIWebView *)webViewPDF
{
CGRect origframe = webViewPDF.frame;
NSString *heightStr = [webViewPDF stringByEvaluatingJavaScriptFromString:#"document.body.scrollHeight;"]; // Get the height of our webView
int height = [heightStr intValue];
CGFloat maxHeight = kDefaultPageHeight - 2*kMargin;
int pages = floor(height / maxHeight);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [paths objectAtIndex:0];
self.pdfPath = [path stringByAppendingPathComponent:[NSString stringWithFormat:#"Purchase Order.pdf"]];
UIGraphicsBeginPDFContextToFile(self.pdfPath, CGRectZero, nil);
for (int i = 0; i < pages; i++)
{
if (maxHeight * (i+1) > height) {
CGRect f = [webViewPDF frame];
f.size.height -= (((i+1) * maxHeight) - height);
[webViewPDF setFrame: f];
}
UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, kDefaultPageWidth, kDefaultPageHeight), nil);
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(currentContext, kMargin, kMargin);
[webViewPDF.layer renderInContext:currentContext];
}
UIGraphicsEndPDFContext();
[webViewPDF setFrame:origframe];
[[[webViewPDF subviews] lastObject] setContentOffset:CGPointMake(0, 0) animated:NO];
}
I hope this makes sense....Does anyone have any suggestions on how to fix this, so the PDF is not cut off?
I forgot to mention these variables:
#define kDefaultPageHeight 850
#define kDefaultPageWidth 850
#define kMargin 50
Here is my share button:
- (IBAction)Share:(id)sender {
NSData *pdfData = [NSData dataWithContentsOfFile:self.pdfPath];
UIActivityViewController * activityController = [[UIActivityViewController alloc] initWithActivityItems:#[pdfData] applicationActivities:nil];
UIPopoverController *popup = [[UIPopoverController alloc] initWithContentViewController:activityController];
[popup presentPopoverFromRect:CGRectMake(self.view.frame.size.width - 36, 60, 0, 0)inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}
I've done this in the past using UIPrintPageRenderer. It's a more versetile way of creating a PDF from a UIWebView, and it's been working well for me so far. I've tested this solution with Xcode 6 and iOS 8.2. Also, tried printing the resulting PDF and everything printed out fine.
When I read the OP, I did some testing with various page sizes, to see if I can get a blank PDF. There are a few key items that I identified, that could contribute to a blank PDF file. I've identified them in the code.
When webViewDidFinishLoad() gets called, the view might not be 100% loaded. A check is necessary, to see if the view is still loading. This is important, as it might be the source of your problem. If it's not, then we are good to go. There is a very important note here. Some web pages are loaded dynamically (defined in the page itself). Take youtube.com for example. The page displays almost immediately, with a "loading" screen. This will trick our web view, and it's "isLoading" property will be set to "false", while the web page is still loading content dynamically. This is a pretty rare case though, and in the general case this solution will work well. If you need to generate a PDF file from such a dynamic loading web page, you might need to move the actual generation to a different spot. Even with a dynamic loading web page, you will end up with a PDF showing the loading screen, and not an empty PDF file.
Another key aspect is setting the printableRect and pageRect. Note that those are set separately. If the printableRect is smaller than the paperRect, you will end up with some padding around the content - see code for example. Here is a link to Apple's API doc with some short descriptions for both.
The example code below adds a Category to UIPrintPageRenderer to create the actual PDF data. The code in this sample has been put together using various resources online in the past, and I wasn't able to find which ones were used to credit them properly.
#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's 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, set to a standard A4 page size. It can be edited to meet your needs.
#define PDFSize CGSizeMake(595.2,841.8)
In order to create your PDF file in memory, you need to draw the layer of the UIWebBrowserView instance that lies underneath the UIWebView's scrollView. In order to do that, try changing your renderInContext: call the following way :
UIView* contentView = webViewPDF.scrollView.subviews.firstObject;
[contentView.layer renderInContext:currentContext];
Also, if you target iOS >= 7.0, then you can avoid using renderInContext: and use one of the snapshotViewAfterScreenUpdates:
or drawViewHierarchyInRect:afterScreenUpdates: methods.
This question already has answers here:
Creating PDF file from UIWebView
(6 answers)
Closed 5 years ago.
In my iOS application, I want to create a PDF from UIWebView/UIView (including subviews). In my app, I will first load the original incoming PDF in UIWebView, and then add an image as a subview on UIWebView. I want to create a PDF from the UIWebview with this image (subview) with original clarity and no data loss.
PS : Image in rendered PDF should be in the same place as in the UIWebView.
I am able to create a PDF from UIWebView, but it lacks the PDF clarity and creates a border issue.
Can anyone please provide a clear solution for PDF rendering from UIWebView (including subviews)?
EDITED CONTENT:
Above is the screenshot of UIWebView. Signature(test) is the image in the subview. I want to render this as a PDF with clarity and without any data loss.
In the below answers, UIPrintPageRenderer renders the PDF from UIWebView, but it ignores the subviews above UIWebView. This is the major issue with this option.
Another answer using the createPDFfromUIView method lacks the original clarity:
-(void)createPDFfromUIView:(UIView*)aView saveToDocumentsWithFileName:(NSString*)aFilename;
A border issue also occurs with this method.
I have also tried to write on the PDF directly, without taking a screenshot, using the below code from this reference.
- (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];
}
It does the job. However, (x,y) coordinates in UIWebView differ from the original PDF coordinates, so I can't map the exact coordinates to draw on the PDF to render.
Hopefully, this clears up my issue. Please suggest a way to resolve my issue. If it is likely impossible, please suggest the iOS PDF kit/SDK that meets my requirement.
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");
}
}
-(void)createPDFfromUIView:(UIView*)aView saveToDocumentsWithFileName:(NSString*)aFilename
{
// Creates a mutable data object for updating with binary data, like a byte array
UIWebView *webView = (UIWebView*)aView;
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);
[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 stringByAppendingPathComponent:aFilename];
// instructs the mutable data object to write its context to a file on disk
[pdfData writeToFile:documentDirectoryFilename atomically:YES];
[webView setFrame:frame];
}
My app takes in the contents of a UIWebView and generates a PDF of the web page. This works fine on smaller pages but when it reaches about 10 pages it crashes "Due to Memory Pressure". Also, this is an ARC app.
The predominant answer I have seen is to use UIGraphicsBeginPDFContextToFile instead of UIGraphicsBeginPDFContextToData and after changing to use File I still get a Memory Pressure crash. I don't understand why it's not clearing the pages from memory. I also added the #autoreleasepool { ... } in the loop as recommended in another question. Any ideas on what I am doing wrong here?
Here's the PDF creation code:
UIGraphicsBeginPDFContextToFile(dataFile, CGRectZero, nil);
for (int i = 0; i < pages; i++) {
#autoreleasepool {
NSLog(#"Creating Page %i", i);
// Check to see if page draws more than the height of the UIWebView
if ((i+1) * 720 > height) {
CGRect f = [_appWebView frame];
f.size.height -= (((i+1) * 720.0) - height);
[_appWebView setFrame: f];
}
UIGraphicsBeginPDFPage();
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(currentContext, 36, 36); // Translate for 0.5" margins
[[[_appWebView subviews] lastObject] setContentOffset:CGPointMake(0, 720 * i) animated:NO];
[_appWebView.layer renderInContext:currentContext];
}
}
UIGraphicsEndPDFContext();
Here's the full method if it helps any:
-(void) generatePDF {
startingFrame = _appWebView.frame;
// Memory warning seems to happen on almost every PDF, clear cache here to be proactive.
[[NSURLCache sharedURLCache] removeAllCachedResponses];
UIWebView *webView = [[UIWebView alloc] initWithFrame: CGRectMake(0, 0, 6.5 * 72, 9 * 72)];
[webView setDelegate: self];
// Adjust to letter size paper size in portrait mode
CGRect frame = _appWebView.frame;
frame.size.height = 10*72; // 11" - 1" Margins = 720px (72px / inch)
frame.size.width = 7.5*72; // 8.5 - 1" Margins = 612px (72px / inch)
_appWebView.frame = frame;
[_appWebView stringByEvaluatingJavaScriptFromString:#"window.scroll(0, 0);"];
// Get the height of our webView
NSString *heightStr = [_appWebView stringByEvaluatingJavaScriptFromString:#"document.body.scrollHeight;"];
int height = [heightStr intValue];
// Get the number of pages needed to print. 10 * 72 = 720
int pages = ceil(height / 720.0);
// File
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *dataFile = [documentsDirectory stringByAppendingPathComponent:#"Configuration.pdf"];
NSLog(#"File: %#", dataFile);
UIGraphicsBeginPDFContextToFile(dataFile, CGRectZero, nil);
for (int i = 0; i < pages; i++) {
#autoreleasepool {
NSLog(#"Creating Page %i", i);
// Check to see if page draws more than the height of the UIWebView
if ((i+1) * 720 > height) {
CGRect f = [_appWebView frame];
f.size.height -= (((i+1) * 720.0) - height);
[_appWebView setFrame: f];
}
UIGraphicsBeginPDFPage();
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(currentContext, 36, 36); // Translate for 0.5" margins
[[[_appWebView subviews] lastObject] setContentOffset:CGPointMake(0, 720 * i) animated:NO];
[_appWebView.layer renderInContext:currentContext];
}
}
UIGraphicsEndPDFContext();
// Adjust to original size
_appWebView.frame = startingFrame;
}
I don't know of a reason you are getting the memory error, but I had a similar issue with searching of PDF's. Basically the OS was loading the entire PDF into memory, then searching, then removing the pdf even thought I was going page by page. My solution was to only do one page at a time, and that resolved the memory issue for me.
My code looks like this:
NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
operationQueue.MaxConcurrentOperationCount = 1;
for(int i = 1; i <= totalPages; i++)
{
// a block of operation
[operationQueue addOperationWithBlock: ^ {
}];
}
I've tried to create PDF from HTML (webview). I did it. But, the problem i'm facing badly is i'm getting 1 vertical & 1 horizontal line on each page. As i attached in this link.
Click for image
Zoom it if u can't see the lines.
I've tried this code
// 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, webView.bounds, nil);
UIGraphicsBeginPDFPage();
CGContextRef pdfContext = UIGraphicsGetCurrentContext();
// draws rect to the view and thus this is captured by UIGraphicsBeginPDFContextToData
[webView.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:#"tmp.pdf"];
// instructs the mutable data object to write its context to a file on disk
[pdfData writeToFile:documentDirectoryFilename atomically:YES];
NSLog(#"documentDirectoryFileName: %#",documentDirectoryFilename);
// Creates a mutable data object for updating with binary data, like a byte array
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);
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);
[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();
// instructs the mutable data object to write its context to a file on disk
[pdfData writeToFile:self.PDFpath atomically:YES];
[webView setFrame:frame];
Any one have idea about this ?
Okay, i got it. It wasn't lines the code i was using above makes 4 parts of each page from UIWebView and print them to PDF as image. So it was the gap between those parts.
I'm trying to save all of the contents of a UIScrollView to a .pdf. I found some tutorials for saving the current view, and they all rely on creating a CGContextRef using UIGraphicsGetCurrentContext(). Right now, I capture my view with just
CGContextRef context = UIGraphicsGetCurrentContext();
[myView.layer renderInContext:context];
And that works fine for a plain UIView. However, when I try to pass a UIScrollView as myView, it passes the visible part of the UIScrollView fine, but anything offscreen is just white space. Is there a way I can expand context somehow to get all of the content in my UIScrollView, and not just what is currently visible? I suspect that I can't use UIGraphicsGetCurrentContext() for a UIScrollView, but I don't know what to use instead, and the Apple docs on this aren't really very helpful.
If you have a subview taking the whole content size of the scrollView with the scrolling content you can do it like this:
CGContextRef context = UIGraphicsGetCurrentContext();
UIView *contentView = [scrollView subviews][0];
[contentView.layer renderInContext:context];
If there are multiple views in the scrollView you can do it like this:
UIView *contentView = [[UIView alloc] initWithFrame:CGRectMake(
scrollView.frame.origin.x,
scrollView.frame.origin.y,
scrollView.contentSize.width,
scrollView.contentSize.height)];
for(UIView *view in [scrollView subviews]){
[contentView addSubview: view];
}
CGContextRef context = UIGraphicsGetCurrentContext();
[contentView.layer renderInContext:context];
Then you need to get the views back into the scrollView. Probably there is a way to copy them but I am not sure how. Anyhow here is what should work:
for(UIView *view in [contentView subviews]){
[view removeFromSuperView];
[scrollView addSubview:view];
}
You can set frame of UIScrollView equal to content size of it and content offset to 0 before calling renderInContext. After that revert frame to original.
myView.frame = CGRectMake(myView.frame.origin.x,myView.frame.origin.y,myView.contentSize.with,myView.contentSize.height);
This code i used to make pdf from uiscrollview and it does help but it will not be as good as if we draw on pdf -- please have look -- Pdf from UIScrollView
- (void) createPDF
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *directroyPath = nil;
directroyPath = [documentsDirectory stringByAppendingPathComponent:#"temp"];
NSString *filePath = [directroyPath stringByAppendingPathComponent:#"test.pdf"];
// check for the "PDF" directory
NSError *error;
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
} else {
[[NSFileManager defaultManager] createDirectoryAtPath:directroyPath
withIntermediateDirectories:NO
attributes:nil
error:&error];
}
CGContextRef pdfContext = [self createPDFContext:_scrollView2.bounds path:(CFStringRef)filePath];
NSLog(#"PDF Context created");
/*
Here limit of i is no of pages in your uiscrollview or
you can use hit and trial here because there is a
length of page is going to be equal to
the visible size of uiscrollView in your application
*/
for (int i = 0 ; i< 2 ; i++)
{
// page 1
CGContextBeginPage (pdfContext,nil);
//turn PDF upsidedown
CGAffineTransform transform = CGAffineTransformIdentity;
//here 365 is equal to the height of myScrollView.frame.size.height
transform = CGAffineTransformMakeTranslation(0, (i+1) * 365);
transform = CGAffineTransformScale(transform, 1.0, -1.0);
CGContextConcatCTM(pdfContext, transform);
//Draw view into PDF
[_scrollView2.layer renderInContext:pdfContext];
CGContextEndPage (pdfContext);
[_scrollView2 setContentOffset:CGPointMake(0, (i+1) * 365) animated:NO];
}
CGContextRelease (pdfContext);
}
- (CGContextRef) createPDFContext:(CGRect)inMediaBox path:(CFStringRef) path
{
CGContextRef myOutContext = NULL;
CFURLRef url;
url = CFURLCreateWithFileSystemPath (NULL, path,
kCFURLPOSIXPathStyle,
false);
if (url != NULL) {
myOutContext = CGPDFContextCreateWithURL (url,
&inMediaBox,
NULL);
CFRelease(url);
}
return myOutContext;
}
Check ScrollViewToPDF example and understand it.
It uses same scrollview's layer renderInContext but here PDF is created according to your requirement such as one page PDF or multiple page PDF
Note : It captures all visible as well as invisible part of scrollView