Memory Pressure Crash When Generating PDF - ios

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: ^ {
}];
}

Related

Objective-C Issues with UIWebView to PDF

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.

Best way to generate PDF from UIWebView/UIView in iOS [duplicate]

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];
}

Memory increases when lazy loading images in UIScrollView iOS7

My app continues to increase in 'live bytes' by about 600kb every time I scroll to a new image. I am loading my images lazily, meaning only 3 at a time, into a UIScrollView that pages horizontally. I have run Xcode instruments and I believe I have tracked the problem to this line:
newPageView = [[UIImageView alloc] initWithImage:[self.album objectAtIndex:page]];
Every page that gets loaded creates a new UIImageView instance, and for some reason, the space is held in memory. I am using ARC and XCode5. Since there is no way to 'dealloc' objects in ARC, what is the best way to free up this memory?
Here's a snapshot of my instruments showing the images that keep taking up the memory:
I have seen this question proposed in other areas online but could not find an answer that helped. I'm fairly new to coding but very willing to learn, any references would be greatly appreciated! thanks!
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.pageCount = self.album.count;
// Set up the array to hold the views for each page
self.pageViews = [[NSMutableArray alloc] init];
for (NSInteger i = 0; i < self.pageCount; ++i) {
[self.pageViews addObject:[NSNull null]];
}
NSInteger p = self.page;
CGFloat w = self.scrollView.bounds.size.width;
[self.scrollView setContentOffset:CGPointMake(p*w,0) animated:YES];
// Set up the content size of the scroll view
CGSize pagesScrollViewSize = self.scrollView.frame.size;
self.scrollView.contentSize = CGSizeMake(pagesScrollViewSize.width * self.pageCount, pagesScrollViewSize.height);
// Load the initial set of pages that are on screen
[self loadVisiblePages];
}
- (void)loadVisiblePages {
// First, determine which page is currently visible
CGFloat pageWidth = self.scrollView.frame.size.width;
NSInteger page = (NSInteger)floor((self.scrollView.contentOffset.x * 2.0f + pageWidth) / (pageWidth * 2.0f));
// Keeps track of which image is showing, for passing to child view controller
self.currentImage = [self.album objectAtIndex:page];
self.title =[NSString stringWithFormat:#"%d of %d", [self.album indexOfObject:self.currentImage]+1, self.pageCount];
// Work out which pages we want to load
NSInteger firstPage = page - 1;
NSInteger lastPage = page + 1;
// Purge anything before the first page
for (NSInteger i=0; i<firstPage; i++) {
[self purgePage:i];
}
for (NSInteger i=firstPage; i<=lastPage; i++) {
[self loadPage:i];
}
for (NSInteger i=lastPage+1; i<self.pageCount; i++) {
[self purgePage:i];
}
}
- (void)loadPage:(NSInteger)page {
if (page < 0 || page >= self.pageCount) {
// If it's outside the range of what we have to display, then do nothing
return;
}
// Load an individual page, first seeing if we've already loaded it
UIView *pageView = [self.pageViews objectAtIndex:page];
// create an instance of imageView to be used as the newPageView
UIImageView *newPageView;
if ((NSNull*)pageView == [NSNull null]) {
CGRect frame = self.scrollView.bounds;
frame.origin.x = frame.size.width * page;
frame.origin.y = 0.0f;
newPageView = [[UIImageView alloc] initWithImage:[self.album objectAtIndex:page]];
newPageView.contentMode = UIViewContentModeScaleAspectFit;
newPageView.frame = frame;
[self.scrollView addSubview:newPageView];
[self.pageViews replaceObjectAtIndex:page withObject:newPageView];
}
}
- (void)purgePage:(NSInteger)page {
if (page < 0 || page >= self.pageCount) {
// If it's outside the range of what we have to display, then do nothing
return;
}
// Remove a page from the scroll view and reset the container array
UIView *pageView = [self.pageViews objectAtIndex:page];
if ((NSNull*)pageView != [NSNull null]) {
[pageView removeFromSuperview];
[self.pageViews replaceObjectAtIndex:page withObject:[NSNull null]];
[self.album replaceObjectAtIndex:page withObject:[NSNull null]];
}
}
#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
[self loadVisiblePages];
}
ARC tries to release memory automatically so you don't have to worry about doing so.
However, you can kind of 'mark' objects so they can be released by 'niling' them:
yourobject = nil;
this kind of tells the IOS device that the object is not being used and can be released. If you're loading images into a scrollview, that means as the user scrolls down, there is content still in memory that is not on-screen and therefore is not needed. You can get rid of these images and then load them again when the scrollview gets near a certain point.
You might find an answer in this question (which is very similar to yours) helpful: Memory pressure in app
It's difficult to give an answer without see your code, but i suppose when you speak about "Lazy loading", you mean you only add your image to the scrollview when you need. But are you removing the images from the scrollview when they are not displayed?
I don't know which kind of display you want, but take a look on UICollectionView. Collection view manage the memory itself and only display cells when needed and UICollectionViewLayout allows you to customize the collection view.
I've changed my code to resize the images as they are loaded as followed:
- (void)loadPage:(NSInteger)page {
if (page < 0 || page >= self.pageCount) {
// If it's outside the range of what we have to display, then do nothing
return;
}
// Load an individual page, first seeing if we've already loaded it
UIView *pageView = [self.pageViews objectAtIndex:page];
// create an instance of imageView to be used as the newPageView
UIImageView *newPageView;
if ((NSNull*)pageView == [NSNull null]) {
CGRect frame = self.scrollView.bounds;
frame.origin.x = frame.size.width * page;
frame.origin.y = 0.0f;
self.resizeImage = [self.album objectAtIndex:page];
UIImage *theImage = [self resizeImage:self.resizeImage toWidth:320.0f andHeight:480.0f];
newPageView = [[UIImageView alloc] initWithImage:theImage];
newPageView.contentMode = UIViewContentModeScaleAspectFit;
newPageView.frame = frame;
[self.scrollView addSubview:newPageView];
[self.pageViews replaceObjectAtIndex:page withObject:newPageView];
}
}
- (UIImage *)resizeImage:(UIImage *)image toWidth:(float)width andHeight:(float)height {
CGSize newSize = CGSizeMake(width, height);
CGRect newRectangle = CGRectMake(0, 0, width, height);
UIGraphicsBeginImageContext(newSize);
[self.resizeImage drawInRect:newRectangle];
UIImage *resizedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return resizedImage;
}
This seems to be holding the memory at a stable place with no permanent increase in memory consumption. I am not sure if this is the best way to solve this problem so if anyone has any better ideas, please provide help.

Integrating e-Signature in pdf file - ios, issue in co-ordinates

Am trying to integrate the signature in a pdf file by fetching the signature from document directory and could place it on the pdf file on fixed position say (50,50). But when trying to integrate the signature by user's tapping position, it is not placed at appropriate position.
I screenshot of the signature added at multiple position of the pdf file is shown below.
Here I tapped at each and every position of the pdf file, but signature is added only at the centre of the pdf file,
CGPoint tapLocation = [gesture locationInView: self.view];
NSLog(#"tapped location is %# \n",NSStringFromCGPoint(tapLocation));
NSInteger x,y;
x=tapLocation.x;
y=tapLocation.y;
CGRect imageRect = CGRectMake(x,568-y, image.size.width, image.size.height);
Adding signature at tapped location is not possible here, but i tried translateCTM and ScaleCTM that also yields the same result. What else to be done, for getting the signature at appropriate tapping position.
UPDATED QUESTION
webView= [[UIWebView alloc] initWithFrame:CGRectMake(0, 60, 320, 568)];
- (void) singleTap:(UITapGestureRecognizer*)gesture
{
// handle event
NSLog(#"single tap is handled");
CGPoint tapLocation = [gesture locationInView:webView];
NSLog(#"tapped location is %# \n",NSStringFromCGPoint(tapLocation));
NSInteger x,y;
x=tapLocation.x;
y=tapLocation.y;
NSLog(#"location:x %d\n",x);
NSLog(#"location:y %d\n",y);
CGPoint pointInView1 = [webView convertPoint:tapLocation toView:self.window];//change of +80 in y
NSLog(#"pointinview is %# \n",NSStringFromCGPoint(pointInView1));
xy = pointInView1.x;
yz = pointInView1.y;
if (entered==1)
{
// CFStringRef path;
CFURLRef url;
url = (CFURLRef)CFBridgingRetain([NSURL fileURLWithPath:documentDirectoryPath]);
CGPDFDocumentRef myDocument;
myDocument = CGPDFDocumentCreateWithURL((CFURLRef)url);
// Create PDF context
CGContextRef pdfContext = CGPDFContextCreateWithURL(url, NULL, NULL);
int totalPages = (int)CGPDFDocumentGetNumberOfPages(myDocument);
NSLog(#"no. of pages in pdf is %d \n",totalPages);
//alter each page of a pdf
for (int currentPage = 1; currentPage <= totalPages; currentPage++)
{
CGPDFContextBeginPage(pdfContext, NULL);
UIGraphicsPushContext(pdfContext);
CGContextDrawPDFPage(UIGraphicsGetCurrentContext(), CGPDFDocumentGetPage(myDocument, currentPage)); //"page" is current pdf page to be signed
if (page == currentPage)
{
NSString *filePath = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"Image.png"];// "image.png" is the saved user's signature in document directory
image = [[UIImage alloc] initWithContentsOfFile:filePath];
// Translate the origin of the coordinate system at the
// bottom left corner of the page rectangle.
// CGContextTranslateCTM(pdfContext, 0,1);
// Reverse the Y axis to grow from bottom to top.
// CGContextScaleCTM(pdfContext, 1, 1);
CGRect imageRect = CGRectMake(x,568-y, image.size.width, image.size.height);
CGContextDrawImage(UIGraphicsGetCurrentContext(), imageRect, image.CGImage);
}
// Clean up
UIGraphicsPopContext();
CGPDFContextEndPage(pdfContext);
}
CGPDFContextClose(pdfContext);
// _sign_label.text = #"";
}
NSURLRequest *request = [NSURLRequest requestWithURL:targetURL];
[webView loadRequest:request];
[self.view addSubview:webView];
}

White lines when creating PDF from HTML (webview)

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.

Resources