1

I need to generate PDF more than 60 pages and need to Print it, but in iPhone & iPad memory Ram raises to 350.50MB-500.00MB and Crashes .

For Reducing memory->Running in dispatch queues also that doesn't help

Can't find the solution for this . Plz help me in this ...

and referred below link but doesn't help

Cannot create PDF document with 400+ pages on iOS

-(NSData*)getPdfFullLineSheetiPhone:(UIScrollView *)tableView GridCount:(NSInteger)count{
// -- first page height, rest pages height: adjust to get it right
 #define FIRST_PAGE_HEIGHT_FULLSON 1040
 #define REST_PAGES_HEIGHT_FULLSON 1090//1420
 #define WIDTH_FULLSO_PORTRAITN 400

CGSize fittedSize;
CGRect priorBounds = tableView.frame;
// - the '200' is the cell height for estimating how many pages, and 200/3 is ROw calculation(How many rows in GMGridView)
fittedSize =CGSizeMake(WIDTH_FULLSO_PORTRAITN,  count * 200/3);
tableView.bounds = CGRectMake(0, 0, fittedSize.width, fittedSize.height);

Generating Pages Code Starts

CGRect pdfPageBounds;
// Standard US Letter dimensions 8.5" x 11"
pdfPageBounds = CGRectMake(0, 0, 768/1.8, REST_PAGES_HEIGHT_FULLSON/1.79);

NSMutableData *pdfData = [[NSMutableData alloc] init];



UIGraphicsBeginPDFContextToData(pdfData, pdfPageBounds, nil);

int pageno=0;
{
    // do page1
    CGRect pdfPageBoundsPage1;
    pdfPageBoundsPage1 = CGRectMake(0,0,768/1.8, FIRST_PAGE_HEIGHT_FULLSON/1.7);
    UIGraphicsBeginPDFPageWithInfo(pdfPageBoundsPage1, nil);
    {
        CGContextTranslateCTM(UIGraphicsGetCurrentContext(), 10, 0);
        [tableView.layer renderInContext:UIGraphicsGetCurrentContext()];

        pageno ++;
    }
  //Rest of Pages
    for (CGFloat pageOriginY = FIRST_PAGE_HEIGHT_FULLSON/1.7; pageOriginY < fittedSize.height; pageOriginY += REST_PAGES_HEIGHT_FULLSON/1.79)
    {
        @autoreleasepool {
        UIGraphicsBeginPDFPageWithInfo(pdfPageBounds, nil);
        {
            CGContextTranslateCTM(UIGraphicsGetCurrentContext(), 10, -pageOriginY);
            [tableView.layer renderInContext:UIGraphicsGetCurrentContext()];


            pageno ++;
        }
}
    }
}
UIGraphicsEndPDFContext();
tableView.bounds = priorBounds;
return pdfData;
 }

Memory Raises in iPad4 whereas in iPad Mini 180-240MB nd crashes enter image description here

Community
  • 1
  • 1
Sanju
  • 1,148
  • 11
  • 26
  • I already included that link in my description above . I didn't find the solution in that link @ShahabQureshi – Sanju May 26 '16 at 13:01
  • why are you not using @autorelease pool atleat in for llop ? – maddy May 26 '16 at 13:09
  • i tried using @autoreleasepool{ } also but it doesn't shows any effect. @Alok – Sanju May 26 '16 at 13:17
  • where can u show code ? – maddy May 26 '16 at 13:18
  • updated code , can you check once @Alok – Sanju May 26 '16 at 13:22
  • check my edit and use this code – maddy May 26 '16 at 13:30
  • thnx for editing lemme test and see @Alok – Sanju May 26 '16 at 13:34
  • By using renderInContext: you are creating a bitmap of every page. There are two things you could try: draw individual graphics objects if you can get them or create jpegs from your rendered layers and draw those into the PDF context. –  May 26 '16 at 14:57
  • 3
    Use `UIGraphicsBeginPDFContextToFile` instead of `UIGraphicsBeginPDFContextToData`. – rmaddy May 26 '16 at 15:03
  • how can i get file reference ? Plz refer my parameters what i am sending to generate Pdf@rmaddy – Sanju May 27 '16 at 04:28
  • I see some useful link http://stackoverflow.com/questions/2975240/cgcontextdrawpdfpage-taking-up-large-amounts-of-memory/4225998#4225998 Can you please help in this how can i change in my code like this or add @Alok. rmaddy . Michael – Sanju May 27 '16 at 04:30
  • @MichaelL it well be great help of your if you provide some link. what i understand first create UIImage then draw Image on PDF really ? will not it be slower ? help with link – maddy May 27 '16 at 05:50
  • so what code are you using please update . and refrase your question how much pages you are able to process ? – maddy May 27 '16 at 09:01
  • @Alok plz refer below answer UIGraphicsBeginPDFContextToFile approach as per ur suggestion – Sanju May 27 '16 at 09:23
  • Yes, it will be a bit slower, because you are first creating a bitmap using renderInContext, and then converting the bitmap to a JPEG. However, the size of your PDF will be much smaller. See http://stackoverflow.com/questions/15223630/reduce-pdf-size-objective-c –  May 28 '16 at 15:33

2 Answers2

1

you have to construct your code some thing like this:

UIGraphicsBeginPDFContextToFile( pdfPath, CGRectZero, nil );// as per rMaddy
UIGraphicsBeginPDFPageWithInfo();
CGContextRef pdfContext = UIGraphicsGetCurrentContext();
[tableView.layer renderInContext:pdfContext];
UIGraphicsEndPDFContext();

here: file namecan be like this:

NSString *newPDFName = [NSString stringWithFormat:@”%@.pdf”, @"whatEverNameYouWant"];

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);

    NSString *documentsDirectory = [paths objectAtIndex:0];


    NSString *pdfPath = [documentsDirectory stringByAppendingPathComponent:newPDFName];

    NSLog(@”%@”,pdfPath);

basically the main benefit of this approach will be reduce NSData which is creating memory pressure. over all code will look some thing this:

// Set up we the pdf we're going to be generating is
UIGraphicsBeginPDFContextToFile(pdfPath, CGRectZero, nil);
int i = 0;
for ( ; i < pages; i++) 
{
  @autoreleasepool{
     // Specify the size of the pdf page
     UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, kDefaultPageWidth, kDefaultPageHeight), nil);
     CGContextRef currentContext = UIGraphicsGetCurrentContext();
     // Move the context for the margins
     CGContextTranslateCTM(currentContext, kMargin, kMargin);
     // draw the layer to the pdf, ignore the "renderInContext not found" warning. 
     [tableView.layer.layer renderInContext:currentContext];
  }
}
// all done with making the pdf
UIGraphicsEndPDFContext();

Thats it !! you can take care of your calculation

maddy
  • 4,001
  • 8
  • 42
  • 65
  • @michaeL approach is still misssing in above answer i can not get it : "By using renderInContext: you are creating a bitmap of every page. There are two things you could try: draw individual graphics objects if you can get them or create jpegs from your rendered layers and draw those into the PDF context". May be michael can help here – maddy May 27 '16 at 05:45
  • I tried above code UIGraphicsBeginPDFPageWithInfo but it still crashes when i give 600-1000 & greater than tableview rows count to generate PDF. that means more than 60 pages. Can i post the code ?.@Alok – Sanju May 27 '16 at 07:39
  • No Crash Log . Just App Quits & showing : Lost Connection to iPad – Sanju May 27 '16 at 08:54
  • man how much pages now you are able to not just talk 60 to 600? how is memory graph now ? – maddy May 27 '16 at 08:55
0

It is not the answer for above question , it is another Code which was tried for to generate PDf using

UIGraphicsBeginPDFPageWithInfo. This approach also crashes for more than 500 rows nothing but it comes around 56 Pages

After this approach after returning PDF Data when i assign that PDF Data to UIPrinterInteractionController Action -

It shows , SO i am unable to calculate Pages

Print-Job failed: Printer exists.
2016-05-27 00:37:26.131 APPName[9078:2952235] \032Send\032to\032Mac\032@\032macminiB._ipp._tcp.local.: startJob not called.

Note : whereas this Printer error doesn't shows in Above code which i posted above with UIGraphicsBeginPDFContextToData

-(NSData *)getPdfSimpleSOTr:(UITableView *)tableView{

#define FIRST_PAGE_HEIGHT 1188
#define REST_PAGES_HEIGHT 1176.5

CGSize fittedSize;

CGRect  priorBounds;

// 140208 dan - Comment: save the WIDTH
CGRect savedFrame = tableView.frame;
// 140207 dan - force portrait width
priorBounds = tableView.frame;
priorBounds.size.width=768; // put into Portrait
tableView.frame = priorBounds;

fittedSize = [tableView sizeThatFits:CGSizeMake(priorBounds.size.width, ([tableView numberOfRowsInSection:0] * 49) + 529)];
tableView.bounds = CGRectMake(0, 0, fittedSize.width, fittedSize.height);
CGRect pdfPageBounds;
pdfPageBounds = CGRectMake(0, -12, 768, REST_PAGES_HEIGHT);

File Name & Path

NSString *newPDFName = [NSString stringWithFormat:@"%@.pdf", @"AppName"];

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);

NSString *documentsDirectory = [paths objectAtIndex:0];


NSString *pdfPath = [documentsDirectory stringByAppendingPathComponent:newPDFName];

NSLog(@"%@",pdfPath);

Generating Pages

// Set up we the pdf we're going to be generating is
UIGraphicsBeginPDFContextToFile(pdfPath, CGRectZero, nil);

int pageno=0;
{
      CGRect pdfPageBoundsPage1 = CGRectMake(0,0,768, FIRST_PAGE_HEIGHT+15);//15
    UIGraphicsBeginPDFPageWithInfo(pdfPageBoundsPage1, nil);

    {
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextTranslateCTM(context, 10, 0);
        [tableView.layer renderInContext:context];
        pageno ++;
    }

for (CGFloat pageOriginY = FIRST_PAGE_HEIGHT; pageOriginY < fittedSize.height; pageOriginY += REST_PAGES_HEIGHT)
{
    @autoreleasepool{
        // Specify the size of the pdf page
        UIGraphicsBeginPDFPageWithInfo(pdfPageBounds, nil);
        CGContextRef context = UIGraphicsGetCurrentContext();
        // Move the context for the margins
        CGContextTranslateCTM(context, 10, -pageOriginY);
        // draw the layer to the pdf, ignore the "renderInContext not found" warning.
        [tableView.layer renderInContext:context];
    }
}

}
// all done with making the pdf
UIGraphicsEndPDFContext();

After GraphicsEnd retrieving NSData from FilePath

   NSData *pdfData;
   if([[NSFileManager defaultManager] fileExistsAtPath:pdfPath])
 {
   pdfData = [[NSFileManager defaultManager] contentsAtPath:pdfPath];
  }
  else
  {
    NSLog(@"File not exits");
  }

tableView.bounds = priorBounds;
// 140208 dan - Comment: restored the saved WIDTH
tableView.frame=savedFrame ;

return pdfData;

  }
Sanju
  • 1,148
  • 11
  • 26
  • Is this approach is correct ? @Alok Or Any wrong i did ? – Sanju May 27 '16 at 09:44
  • we are not sitting here to work on behalf of you man !! no one will help you if you will not take initiative. there was problem previously in your code we help you to make it work ? now in the same question you are saying printer error . Accept above answer and create new question with whet ever error related to printer you are getting – maddy May 27 '16 at 10:53
  • thanks for your time @Alok . I will work around on it .For your effort and Time i upvoted your answer .Thanks again . – Sanju May 27 '16 at 11:31