Issue while generating PDF from Table View - ios

I have to generate PDf from UITableView having multiple sections and rows.
I have generated the pdf as well but the problem is while creating PDF it is cutting the data of some rows and showing on other page.
So Please suggest any dynamic logic that will help in creating PDf having data on the page without going to other Page .
Also Please find code below which I have used to create PDF.
CGRect priorBounds = self.tableView.bounds;
CGSize fittedSize = [self.tableView sizeThatFits:CGSizeMake(priorBounds.size.width, self.tableView.contentSize.height)];
self.tableView.bounds = CGRectMake(0, 0, 612, fittedSize.height);
CGRect pdfPageBounds = CGRectMake(0, 0, 612, 792); // Change this as your need
NSMutableData *pdfData = [[NSMutableData alloc] init];
UIGraphicsBeginPDFContextToData(pdfData, pdfPageBounds, nil); {
for (CGFloat pageOriginY = 0; pageOriginY < fittedSize.height; pageOriginY += pdfPageBounds.size.height) {
UIGraphicsBeginPDFPageWithInfo(pdfPageBounds, nil);
CGContextSaveGState(UIGraphicsGetCurrentContext()); {
CGContextTranslateCTM(UIGraphicsGetCurrentContext(), 0, -pageOriginY);
[self.tableView.layer renderInContext:UIGraphicsGetCurrentContext()];
} CGContextRestoreGState(UIGraphicsGetCurrentContext());
}
} UIGraphicsEndPDFContext();
self.tableView.bounds = priorBounds; // Reset the tableView
// Use the pdfData to
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];
//Get the docs directory
NSString *filePathPDF = [documentsPath stringByAppendingPathComponent:#"image.pdf"]; //Add the file name
[pdfData writeToFile:filePathPDF atomically:YES];
Any help will be appreciated.

After doing a lot R&D on this, finally I got the solution.
I know this to too late to post answer of above question, but I am posting my solution so it may help someone in future.
The trick which I used to avoid this issue is, Run the loop each section wise and took picture of each dynamic cell.
Then I started combining images of cells by below function,
- (UIImage*)imageByCombiningImage:(UIImage*)firstImage withImage:(UIImage*)secondImage {
UIImage *image1 = firstImage;
UIImage *image2 = secondImage;
CGSize size = CGSizeMake(image1.size.width, image1.size.height + image2.size.height);
UIGraphicsBeginImageContext(size);
[image1 drawInRect:CGRectMake(0,0,size.width, image1.size.height)];
[image2 drawInRect:CGRectMake(0,image1.size.height,size.width, image2.size.height)];
UIImage *finalImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//set finalImage to IBOulet UIImageView
return finalImage;
}
and to generate combined image, I used below logic. In that I checked the height of combine image, if it is greater than screen size or not.
Below is my whole logic of code,
CGRect priorBounds = self.tableView.bounds;
CGSize fittedSize = [self.tableView sizeThatFits:CGSizeMake(priorBounds.size.width, self.tableView.contentSize.height)];
self.tableView.bounds = CGRectMake(0, 0, fittedSize.width, fittedSize.height);
pdfViews = [[NSMutableArray alloc] init];
NSMutableData *pdfData = [[NSMutableData alloc] init];
float sections = [self.tableView numberOfSections];
for (int C = 0; C < sections; C++)
{
int rows = 0;
rows = [self.tableView numberOfRowsInSection:C];
for (int I = 0; I < rows; I++)
{
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:I inSection:C];
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
UIGraphicsBeginImageContextWithOptions(cell.bounds.size, cell.opaque, 0.0);
[cell.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *cellImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[pdfViews addObject:cellImage];
}
}
NSArray *pageArray = pdfViews;
UIImage *pdfFinalImage = [[UIImage alloc] init];
UIImage *addOnImage = [[UIImage alloc] init];
NSMutableArray *finalA = [[NSMutableArray alloc] init];
int checkHeight;
checkHeight = 1024;
for (int Z = 0; Z < [pdfViews count]; Z++)
{
if (Z == 0)
{
pdfFinalImage = [pageArray objectAtIndex:Z];
}else if (Z+1 == [pdfViews count])
{
addOnImage = [pageArray objectAtIndex:Z];
if (pdfFinalImage.size.height+addOnImage.size.height > checkHeight)
{
[finalA addObject:pdfFinalImage];
pdfFinalImage = [pageArray objectAtIndex:Z];
[finalA addObject:pdfFinalImage];
}else
{
pdfFinalImage = [self imageByCombiningImage:pdfFinalImage withImage:addOnImage];
[finalA addObject:pdfFinalImage];
}
}else
{
UIImage *heightCheckImage = [pageArray objectAtIndex:Z];
if (pdfFinalImage.size.height+heightCheckImage.size.height > checkHeight)
{
[finalA addObject:pdfFinalImage];
pdfFinalImage = [pageArray objectAtIndex:Z];
}else
{
addOnImage = [pageArray objectAtIndex:Z];
pdfFinalImage = [self imageByCombiningImage:pdfFinalImage withImage:addOnImage];
}
}
}
UIGraphicsBeginPDFContextToData(pdfData, CGRectMake(0, 0, 768, 1024), nil);
for (int IC = 0; IC < [finalA count]; IC++)
{
UIGraphicsBeginPDFPage();
UIImage *mainImage = [finalA objectAtIndex:IC];
NSData *jpegData = UIImageJPEGRepresentation(mainImage, 0.5);
CGDataProviderRef dp = CGDataProviderCreateWithCFData((__bridge CFDataRef)jpegData);
CGImageRef cgImage = CGImageCreateWithJPEGDataProvider(dp, NULL, true, kCGRenderingIntentDefault);
[[UIImage imageWithCGImage:cgImage] drawInRect:CGRectMake(0, 0, mainImage.size.width, mainImage.size.height)];
}
UIGraphicsEndPDFContext();
self.tableView.bounds = priorBounds;
[pdfData writeToFile:tmpPdfPath atomically:YES];

Related

How to Display GIF image from URL in Imageview?

Earlier i used SDWebimage third party to display images, now i removed that 3rd party due some other reason. is there any other way to Display GIF image from URL in Imageview without using third party...
Well you can do it simply by following next steps:
Add the following functions
#import <ImageIO/ImageIO.h>
#import <MobileCoreServices/MobileCoreServices.h>
UIImage *GIFFromData(NSData *data) {
if (!data) {
return nil;
}
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)(data), NULL);
UIImage *image = nil;
if (GIFSourceContainsAnimatedGIF(source)) {
image = GIFFromImageSource(source);
} else {
image = [UIImage imageWithData:data];
}
if (source) {
CFRelease(source);
}
return image;
}
BOOL GIFSourceContainsAnimatedGIF(CGImageSourceRef source) {
return (source && UTTypeConformsTo(CGImageSourceGetType(source), kUTTypeGIF) && CGImageSourceGetCount(source) > 1);
}
UIImage *GIFFromImageSource(CGImageSourceRef source) {
CFRetain(source);
NSUInteger numberOfFrames = CGImageSourceGetCount(source);
NSMutableArray<UIImage *> *images = [NSMutableArray arrayWithCapacity:numberOfFrames];
NSTimeInterval duration = 0.0;
for (NSUInteger i = 0; i < numberOfFrames; ++i) {
CGImageRef image = CGImageSourceCreateImageAtIndex(source, i, NULL);
if (image) {
UIImage *frameImage = [UIImage imageWithCGImage:image scale:1.0 orientation:UIImageOrientationUp];
[images addObject:frameImage];
CFRelease(image);
} else {
continue;
}
duration += GIFSourceGetFrameDelay(source, i);
}
CFRelease(source);
return [UIImage animatedImageWithImages:images duration:duration];
}
NSTimeInterval GIFSourceGetFrameDelay(CGImageSourceRef source, NSUInteger index) {
NSTimeInterval frameDelay = 0;
CFDictionaryRef imageProperties = CGImageSourceCopyPropertiesAtIndex(source, index, NULL);
if (!imageProperties) {
return frameDelay;
}
CFDictionaryRef gifProperties = nil;
if (CFDictionaryGetValueIfPresent(imageProperties, kCGImagePropertyGIFDictionary, (const void **)&gifProperties)) {
const void *durationValue = nil;
if (CFDictionaryGetValueIfPresent(gifProperties, kCGImagePropertyGIFUnclampedDelayTime, &durationValue)) {
frameDelay = [(__bridge NSNumber *)durationValue doubleValue];
if (frameDelay <= 0) {
if (CFDictionaryGetValueIfPresent(gifProperties, kCGImagePropertyGIFDelayTime, &durationValue)) {
frameDelay = [(__bridge NSNumber *)durationValue doubleValue];
}
}
}
}
CFRelease(imageProperties);
return frameDelay;
}
Download your GIF with NSURLSession
Display it
UIImage *image = GIFFromData(data);
UIImageView *view = [[UIImageView alloc] initWithImage:image];
Hope this helps :)
UIImageView* animatedImageView = [[UIImageView alloc] initWithFrame:self.view.bounds];
animatedImageView.animationImages = [NSArray arrayWithObjects:
[UIImage imageNamed:#"image1.gif"],
[UIImage imageNamed:#"image2.gif"],
[UIImage imageNamed:#"image3.gif"],
[UIImage imageNamed:#"image4.gif"], nil];
animatedImageView.animationDuration = 1.0f;
animatedImageView.animationRepeatCount = 0;
[animatedImageView startAnimating];
[self.view addSubview: animatedImageView];
Add animated Gif image in Iphone UIImageView

Converting a UIWebView to PDF/Image gives only one inch wide output

I'm converting a UIWebView to pdf/image with the help of the following code:
NSString *heightStr = [webView stringByEvaluatingJavaScriptFromString:#"document.body.scrollHeight;"];
int height = [heightStr intValue];
CGFloat screenHeight = webView.bounds.size.height;
int pages = ceil(height / screenHeight);
NSMutableData *pdfData = [NSMutableData data];
UIGraphicsBeginPDFContextToData(pdfData, webView.bounds, nil);
CGRect frame = [webView frame];
NSMutableArray *imageArray= [[NSMutableArray alloc]init];
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];
}
UIGraphicsBeginImageContext(frame.size);
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];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
[imageArray insertObject:viewImage atIndex:imageArray.count] ;
UIGraphicsEndImageContext();
}
UIGraphicsEndPDFContext();
[webView setFrame:frame];
//Send all images
NSData *imgData = [self blendImages:imageArray];
//Final Image
UIImage *finalImage = [UIImage imageWithData:imgData];
-(NSData*)blendImages:(NSMutableArray *)arrImage{
// get data from document
CGFloat height=0 ,width=0 ;
UIImage *tempImg = [arrImage objectAtIndex:0] ;
width =tempImg.size.width ;
for (int i = 0 ; i<arrImage.count ; i++){
UIImage *img= [arrImage objectAtIndex:i];
height = img.size.height +height;
}
CGSize size = CGSizeMake(width, height) ;
UIGraphicsBeginImageContext(size);
CGFloat h = 0;
for (int i=0; i<arrImage.count; i++) {
UIImage* uiimage = [arrImage objectAtIndex:i];
[uiimage drawAtPoint:CGPointMake(0, h) blendMode:kCGBlendModeNormal alpha:1.0];
h = uiimage.size.height +h ;
}
NSData *imageData = UIImagePNGRepresentation(UIGraphicsGetImageFromCurrentImageContext());
UIGraphicsEndImageContext();
return imageData;
}
But I'm getting only one inch wide output. Also the whole contains fits in one page and make it unreadable. How to make A4 sized output?
This creates a PDF of a screenshot of a webpage - might help get you started :)
- (IBAction)makePDF:(id)sender
{
UIGraphicsBeginImageContextWithOptions(webView.scrollView.contentSize, webView.scrollView.opaque, 0.0);
webView.scrollView.contentOffset = CGPointZero;
webView.scrollView.frame = CGRectMake(0, 0, webView.scrollView.contentSize.width, webView.scrollView.contentSize.height);
[webView.scrollView.layer renderInContext: UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGRect imageFrame = CGRectMake(0, 0, image.size.width, image.size.height);
NSMutableData *pdfData = [NSMutableData data];
UIGraphicsBeginPDFContextToData(pdfData, imageFrame, nil);
//full screenshot
UIGraphicsBeginPDFPage();
UIImageView *imageView = [[UIImageView alloc] initWithFrame:imageFrame];
[imageView setContentMode:UIViewContentModeScaleAspectFit];
[imageView setImage:image];
[imageView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIGraphicsEndPDFContext();
NSArray *documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
NSString *documentDirectory = [documentDirectories objectAtIndex:0];
NSString *fileName = [NSString stringWithFormat:#"%#.pdf",[NSDate date]];
NSString *path = [documentDirectory stringByAppendingPathComponent:fileName];
// save to disk
[pdfData writeToFile:path atomically:YES];
NSLog(#"pdf in %#", path);
}

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..

Is there different in size of image when we get same using imageWithContentsOfFile and imageNamed

I am drawing images on PDF, but when i get images using imageWithContentsOfFile to draw on PDF then PDF size is 133.6 mb but when i get same images using imageNamed to draw on PDF then PDF size is 568 KB. I am unable to understand why this differece occure?
static int i = 0;
NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"];
NSString *filePath = [path stringByAppendingPathComponent:[NSString stringWithFormat:#"%d.pdf", ++i]];
UIGraphicsBeginPDFContextToFile(filePath, CGRectZero, nil);
for (int pageCounts = 1; pageCounts <= 15; pageCounts++) {
UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, 2000, 1960), nil);
for (int imageCount = 1; imageCount < 9; imageCount++) {
NSString *newFilePath = [[NSBundle mainBundle]pathForResource:[NSString stringWithFormat:#"%d",imageCount] ofType:#"png"];
CGRect rectFImage1 = CGRectMake(15, 400*imageCount, 700, 400);
UIImage *image1 = [UIImage imageWithContentsOfFile:newFilePath];
[image1 drawInRect:rectFImage1];
CGRect rectFImage2 = CGRectMake(800, 400*imageCount, 700, 400);
UIImage *image2 = [UIImage imageWithContentsOfFile:newFilePath];
[image2 drawInRect:rectFImage2];
}
}
UIGraphicsEndPDFContext();
static int i = 0;
NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"];
NSString *filePath = [path stringByAppendingPathComponent:[NSString stringWithFormat:#"%d.pdf", ++i]];
UIGraphicsBeginPDFContextToFile(filePath, CGRectZero, nil);
for (int pageCounts = 1; pageCounts <= 15; pageCounts++) {
UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, 2000, 1960), nil);
for (int imageCount = 1; imageCount < 9; imageCount++) {
CGRect rectFImage3 = CGRectMake(315, 400*imageCount, 700, 400);
UIImage *image3 = [UIImage imageNamed:[NSString stringWithFormat:#"%d.png",imageCount]];
[image3 drawInRect:rectFImage3];
CGRect rectFImage4 = CGRectMake(1200, 400*imageCount, 700, 400);
UIImage *image4 = [UIImage imageNamed:[NSString stringWithFormat:#"%d.png",imageCount]];
[image4 drawInRect:rectFImage4]; }
}
UIGraphicsEndPDFContext();

Loading images on scrollview using lazy loading

I am working on an app in which I need to load nearly 211 images in a scrollview.
What I was doing was I was converting the images in binary format (NSData) and saving them in core data. Then retrieving them and populating them on the scrollview.
it does work, but sometimes it does throw "Memory warning".
I learned that lazy loading is a way to achieve this. But, I am not totally aware of how it is done.
Like, loading 3 or 5 images ahead/back of the image visible currently on the scrollview.
Can any bode help me with a simple example, which would help me understand from scratch ? and would point me in the right direction.
Thank you for your time.
Well, it is not needed to store images into core data. Just take all image URLs into NSMutableArray and try to use following code as per your requirement.Hope this helps you.
Try this code -
friendsScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 470, 320, 100)];
friendsScrollView.contentSize = CGSizeMake([meetUPFrndNameArray count] * 95,50);
friendsScrollView.backgroundColor = [UIColor clearColor];
friendsScrollView.delegate = self;
[self.view addSubview:friendsScrollView];
int imageX = 25,imageY = 20;
int backImageX = 10, backImageY = 10;
int flag = 0;
for (int i = 0; i < [meetUPFrndPhotoArray count]; i++) {
flag ++;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *documentsDirectory = paths[0];
NSString *savedImagePath = [documentsDirectory stringByAppendingPathComponent:meetUPFrndPhotoArray[flag-1]];
UIImage *img1 = [UIImage imageWithContentsOfFile:savedImagePath];
if (!img1 || [UIImagePNGRepresentation(img1) length] <=0)
{
id path = meetUPFrndPhotoArray[flag-1];
path = [path stringByReplacingOccurrencesOfString:#" " withString:#"%20"];
NSURL *url = [NSURL URLWithString:path];
NSMutableArray *arr = [[NSMutableArray alloc] initWithObjects:url, [NSString stringWithFormat:#"%d", flag], nil];
[self performSelectorInBackground:#selector(loadImageInBackground:) withObject:arr];
UIImageView *frndBackgroundImage = [[UIImageView alloc] initWithFrame:CGRectMake(backImageX, backImageY, 80, 80)];
frndBackgroundImage.image = [UIImage imageNamed:#"friend_image_background.png"];
frndBackgroundImage.backgroundColor = [UIColor clearColor];
frndBackgroundImage.layer.borderWidth = 2.0;
frndBackgroundImage.layer.masksToBounds = YES;
frndBackgroundImage.layer.shadowOffset = CGSizeMake(0, 1);
frndBackgroundImage.layer.shadowOpacity = 1;
frndBackgroundImage.layer.shadowRadius = 1.2;
frndBackgroundImage.layer.cornerRadius = 5.0;
frndBackgroundImage.layer.borderColor = [[UIColor clearColor] CGColor];
[friendsScrollView addSubview:frndBackgroundImage];
UIImageView *friendImage = [[UIImageView alloc] initWithFrame:CGRectMake(imageX, imageY, 50, 50)];
friendImage.tag = flag;
friendImage.image = [UIImage imageNamed:#"ic_user.png"];
[friendsScrollView addSubview:friendImage];
}
else
{
UIImageView *frndBackgroundImage = [[UIImageView alloc] initWithFrame:CGRectMake(backImageX, backImageY, 80, 80)];
frndBackgroundImage.image = [UIImage imageNamed:#"friend_image_background.png"];
frndBackgroundImage.backgroundColor = [UIColor clearColor];
frndBackgroundImage.layer.borderWidth = 2.0;
frndBackgroundImage.layer.masksToBounds = YES;
frndBackgroundImage.layer.shadowOffset = CGSizeMake(0, 1);
frndBackgroundImage.layer.shadowOpacity = 1;
frndBackgroundImage.layer.shadowRadius = 1.2;
frndBackgroundImage.layer.cornerRadius = 5.0;
frndBackgroundImage.layer.borderColor = [[UIColor clearColor] CGColor];
[friendsScrollView addSubview:frndBackgroundImage];
UIImageView *friendImage = [[UIImageView alloc] initWithFrame:CGRectMake(imageX, imageY, 50, 50)];
friendImage.tag = flag-1;
friendImage.image = img1;
[friendsScrollView addSubview:friendImage];
}
backImageX = backImageX + 80 + 10;
backImageY = 10;
imageX = imageX + 50 + 25 + 15;
imageY = 20;
}
Here meetUPFrndPhotoArray contains image URLs.
And
For Downloading images in Background -
- (void) loadImageInBackground:(NSArray *)urlAndTagReference{
NSData *imgData = [NSData dataWithContentsOfURL:urlAndTagReference[0]];
UIImage *img = [[UIImage alloc] initWithData:imgData];
NSMutableArray *arr = [[NSMutableArray alloc] initWithObjects:img, urlAndTagReference[1], nil];
[self performSelectorOnMainThread:#selector(assignImageToImageView:) withObject:arr waitUntilDone:YES];
}
For Assigning downloaded image to perticular imageView -
- (void) assignImageToImageView:(NSArray *)imgAndTagReference{
for (UIImageView *checkView in [friendsScrollView subviews] ){
if ([imgAndTagReference count] != 0) {
if ([checkView tag] == [imgAndTagReference[1] intValue]){
[checkView setImage:imgAndTagReference[0]];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *documentsDirectory = paths[0];
NSString *savedImagePath = [documentsDirectory stringByAppendingPathComponent:meetUPFrndPhotoArray[[imgAndTagReference[1] intValue]-1]];
UIImage* imageToSave = [checkView image];
NSData *imageData = UIImagePNGRepresentation(imageToSave);
[imageData writeToFile:savedImagePath atomically:NO];
}
}
}
}
Let me know if this helps you.Thanks in advance.All the best.
Make use of delegate functions, content size and content inset properties of the scrollview
Checkout this library It's a generic UIScrollView that reuses it's subviews like UITableView does (there is a dataSource object which is used to configure scroll view subviews)

Resources