Dustin
Dustin

Reputation: 6803

Render multi-page PDF

I have an app out for testing that does a bunch of stuff, but the end product is a .pdf that uploads to a database. Unfortunately one of my end-users doesn't like the fact that a long .pdf is all one page. The length of the page generated is extremely variable, so I was just generating a single page no matter what. I know that Adobe Acrobat will tile large files onto multiple pages for printing, but the customer is concerned that this may be too difficult for some people -_-

Here's how I'm creating a .pdf right now

- (void)exportAsPDF:(NSString *)filename
{        
    int restorer = mineTable.frame.size.height;

    CGRect temp = CGRectMake(mineTable.frame.origin.x, mineTable.frame.origin.y, mineTable.frame.size.width, 200*formDataStorage.cake.count);
    [self resizeTheTable:temp];

    int addNumber = temp.size.height - temp.origin.y;

    CGRect mediaBox = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height + addNumber);

    NSString *tmpFile = filename;

    CGContextRef ctx = CGPDFContextCreateWithURL((__bridge CFURLRef)[NSURL fileURLWithPath:tmpFile], &mediaBox, NULL);

    //turn PDF upside-down
    CGAffineTransform transform = CGAffineTransformIdentity;
    transform = CGAffineTransformMakeTranslation(0, mediaBox.size.height);
    transform = CGAffineTransformScale(transform, 1.0, -1.0);

    CGPDFContextBeginPage(ctx, NULL);
    CGContextConcatCTM(ctx, transform);

    [self.view setNeedsLayout];
    [self.view setNeedsDisplay];
    [self.view.layer renderInContext:ctx];

    CGPDFContextEndPage(ctx);

    CGPDFContextClose(ctx);
    CFRelease(ctx);
}

As you can see, I resize the view to show all of the cells in the table I'm rendering and then sort of screenshot the view into a .pdf. The user never sees the resized view (it wouldn't all fit on the screen anyway).

Does anyone know how to associate different parts of the created .pdf with different pages? Thanks.

Upvotes: 0

Views: 3051

Answers (2)

Paul Jowett
Paul Jowett

Reputation: 6581

You've already answered yourself, but in case it's helpful you can use a service like Docmosis to generate PDFs from iOS. In your case the issue with pagination would never have occurred because documents "flow" as they are populated based on templates. The downside is you have to be connected to the net.

Upvotes: 1

Dustin
Dustin

Reputation: 6803

I ended up using this code:

- (void)exportAsPDF:(NSString *)filename
{        
    int restorer = mineTable.frame.size.height;
    CGRect temp = CGRectMake(mineTable.frame.origin.x, mineTable.frame.origin.y, mineTable.frame.size.width, 398*formDataStorage.cake.count);
    [self resizeTheTable:temp];

    int addNumber = temp.size.height - temp.origin.y;
    CGRect mediaBox = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height + addNumber);

    NSMutableData *theData = [NSMutableData data];
    CGSize pageSize = CGSizeMake(self.view.frame.size.width, 792);
    UIGraphicsBeginPDFContextToData(theData, CGRectZero, nil);
    CGContextRef pdfContext = UIGraphicsGetCurrentContext();

    NSInteger currentPage = 0;
    BOOL done = NO;

    do {
        UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0.0, pageSize.width, pageSize.height), nil);
        CGContextTranslateCTM(pdfContext, 0, -(pageSize.height*currentPage));
        [self.view.layer renderInContext:pdfContext];

        if ((pageSize.height*(currentPage+1)) > mediaBox.size.height) done = YES;
        else currentPage++;
    } while (!done);

    UIGraphicsEndPDFContext();

    [theData writeToFile:filename atomically:YES];
    NSLog(@"PDF written to: %@", filename);
}

Upvotes: 3

Related Questions