Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I generate a PDF with "real" text content on iOS?

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?

like image 617
Joris Mans Avatar asked Sep 23 '12 21:09

Joris Mans


2 Answers

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

like image 82
Siba Prasad Hota Avatar answered Nov 03 '22 15:11

Siba Prasad Hota


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.

like image 35
Minthos Avatar answered Nov 03 '22 15:11

Minthos