7

I want to generate a good-looking PDF in my iOS 6 app.

I've tried:

  • UIView render in context
  • Using CoreText
  • Using NSString drawInRect
  • Using UILabel drawRect

Here is a code example:

-(CGContextRef) createPDFContext:(CGRect)inMediaBox path:(NSString *) path
{
    CGContextRef myOutContext = NULL;
    NSURL * url;

    url = [NSURL fileURLWithPath:path];
    if (url != NULL) {
        myOutContext = CGPDFContextCreateWithURL ((__bridge CFURLRef) url,
                                                  &inMediaBox,
                                                  NULL);
    }


    return myOutContext;
}

-(void)savePdf:(NSString *)outputPath
{
    if (!pageViews.count)
        return;

    UIView * first = [pageViews objectAtIndex:0];

    CGContextRef pdfContext = [self createPDFContext:CGRectMake(0, 0, first.frame.size.width, first.frame.size.height) path:outputPath];

    for(UIView * v in pageViews)
    {
        CGContextBeginPage (pdfContext,nil);
        CGAffineTransform transform = CGAffineTransformIdentity;
        transform = CGAffineTransformMakeTranslation(0, (int)(v.frame.size.height));
        transform = CGAffineTransformScale(transform, 1, -1);
        CGContextConcatCTM(pdfContext, transform);

        CGContextSetFillColorWithColor(pdfContext, [UIColor whiteColor].CGColor);
        CGContextFillRect(pdfContext, v.frame);

        [v.layer renderInContext:pdfContext];

        CGContextEndPage (pdfContext);
    }

    CGContextRelease (pdfContext);
}

The UIViews that are rendered only contain a UIImageView + a bunch of UILabels (some with and some without borders).

I also tried a suggestion found on stackoverflow: subclassing UILabel and doing this:

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
    BOOL isPDF = !CGRectIsEmpty(UIGraphicsGetPDFContextBounds());
    if (!layer.shouldRasterize && isPDF)
        [self drawRect:self.bounds]; // draw unrasterized
    else
        [super drawLayer:layer inContext:ctx];
}

But that didn't change anything either.

No matter what I do, when opening the PDF in Preview the text parts are selectable as a block, but not character per character, and zooming the pdf shows it is actually a bitmap image.

Any suggestions?

Joris Mans
  • 6,024
  • 6
  • 42
  • 69
  • Can you post a sample code fragment and the output PDF file so I can take a look at them? – iPDFdev Sep 24 '12 at 08:06
  • Did you ever figure this out? Experiencing the "block selection" issue. – JeremyDay Sep 18 '13 at 04:56
  • Doesn't seem to happen now with: `UIGraphicsBeginPDFContextToFile( outputPath, view.bounds, nil ); UIGraphicsBeginPDFPage(); CGContextRef pdfContext = UIGraphicsGetCurrentContext(); [view.layer renderInContext:pdfContext]; UIGraphicsEndPDFContext();` – JeremyDay Sep 18 '13 at 05:31

3 Answers3

2

This Tutorial From Raywenderlich Saved my Day.Hope it will work for you too. http://www.raywenderlich.com/6818/how-to-create-a-pdf-with-quartz-2d-in-ios-5-tutorial-part-2

Siba Prasad Hota
  • 4,779
  • 1
  • 20
  • 40
1

My experience when I did this last year was that Apple didn't provide any library to do it. I ended up importing an open source C library (libHaru). Then I added a function for outputting to it in each class in my view hierarchy. Any view with subviews would call render on its subviews. My UILabels, UITextFields, UIImageViews, UISwitches etc would output their content either as text or graphics accordingly I also rendered background colors for some views.

It wasn't very daunting, but libHaru gave me some problems with fonts so iirc I ended up just using the default font and font size.

Minthos
  • 900
  • 4
  • 13
0

It works good with UILabels except that you have to work around a bug:

Rendering a UIView into a PDF as vectors on an iPad - Sometimes renders as bitmap, sometimes as vectors

netdigger
  • 3,659
  • 3
  • 26
  • 49