Question

I wrote this code snippet that takes an array of UIViews and renders them into a PDF. However, each view is being rendered into a separate page because I can't figure out how to merge PDF pages or render all views into a single page.

Current code:

+ (NSData*)pdfFromViews:(NSArray*)views
{
    NSMutableData* pdf = [NSMutableData data];

    UIGraphicsBeginPDFContextToData(pdf, CGRectZero, nil);
    CGContextRef context = UIGraphicsGetCurrentContext();

    for(UIView* view in views)
    {
        UIGraphicsBeginPDFPageWithInfo(view.bounds, nil);
        [view.layer renderInContext:context];
    }

    UIGraphicsEndPDFContext();

    return pdf;
}

If I only call this line once - UIGraphicsBeginPDFPage() - the views get drawn on top of each other, no matter what changes I make to view.layer.frame or what size CGRect I use for my context.

I'm happy with the current image quality and don't need to add any links or text into the PDF.

I'm looking for a way to merge my resultant PDF pages, or draw my views into a single page. NOTE: I can't add my views as subviews into a common parent view because it messes up my app layout. Ideally, I would do this but UIViews can't be copied.

Was it helpful?

Solution

Shift the origin between renders with CGContextTranslateCTM:

+ (NSData*)pdfFromViews:(NSArray*)views {
    NSMutableData* pdf = [NSMutableData data];
    UIGraphicsBeginPDFContextToData(pdf, CGRectZero, nil);
    UIGraphicsBeginPDFPage();
    CGContextRef context = UIGraphicsGetCurrentContext();

    for(UIView *view in views) {
        [view.layer renderInContext:context];
        CGContextTranslateCTM(context, 0, view.bounds.size.height);
    }

    UIGraphicsEndPDFContext();
    return pdf;
}

You may also want to specify a page size that fits your views. Calculate the size and call UIGraphicsBeginPDFPageWithInfo instead of UIGraphicsBeginPDFPage.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top