Search code examples
pdf-generationios7

Create PDF iOS7


to create a pdf programmaticallly inside my iOS app I followed this tutorial on mobile.tut+:

http://mobile.tutsplus.com/tutorials/iphone/generating-pdf-documents/

but two methods are now deprecated in iOS7, but what xcode suggest to use instead of old methods doesn't seems to work. somebody have an idea?

thanks!

    - (CGRect)addText:(NSString*)text withFrame:(CGRect)frame fontSize:(float)fontSize{
    UIFont *font = [UIFont fontWithName:@"HelveticaNeue-Light" size:fontSize];

    NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];
    paragraph.alignment = NSTextAlignmentNatural;

    NSDictionary*attributi = @{ NSForegroundColorAttributeName: [UIColor blackColor],NSFontAttributeName: font, NSParagraphStyleAttributeName: paragraph};

    NSStringDrawingContext* drawCont = [[NSStringDrawingContext alloc]init];
    drawCont.minimumScaleFactor = 0.0;


    //IOS6 deprecated method

//  CGSize stringSize = [text sizeWithFont:font constrainedToSize:CGSizeMake(_pageSize.width - 2*20-2*20, _pageSize.height - 2*20 - 2*20) lineBreakMode:NSLineBreakByWordWrapping];

//IOS7 method suggested by xcode

    CGRect stringSIZ = [text boundingRectWithSize:CGSizeMake(_pageSize.width - 2*20-2*20, _pageSize.height - 2*20 - 2*20) options:NSStringDrawingUsesLineFragmentOrigin attributes:attributi context:drawCont];

    float textWidth = frame.size.width;

    if (textWidth < stringSIZ.size.width)
        textWidth = stringSIZ.size.width;
    if (textWidth > _pageSize.width)
        textWidth = _pageSize.width - frame.origin.x;

    CGRect renderingRect = CGRectMake(frame.origin.x, frame.origin.y, textWidth, stringSIZ.size.height);

         //IOS6 deprecated method
//    [text drawInRect:renderingRect
//            withFont:font
//       lineBreakMode:NSLineBreakByWordWrapping
//           alignment:NSTextAlignmentNatural];

    //IOS7 method suggested by xcode
    [text drawInRect:renderingRect withAttributes:attributi];

    frame = CGRectMake(frame.origin.x, frame.origin.y, textWidth, stringSIZ.size.height);

    return frame;
}

Solution

  • I create my own class to create pdf as easy as possible in iOS7. if somebody need it, here it is:

    PDFHelper.h

    #import <Foundation/Foundation.h>
    
    @interface PDF : NSObject{
    }
    @property(nonatomic, readwrite) CGSize size;
    @property(nonatomic, strong) NSMutableArray *headerRect;
    
    @property(nonatomic, strong) NSMutableArray *header;
    
    @property(nonatomic, strong) NSMutableArray *imageArray;
    @property(nonatomic, strong) NSMutableArray *imageRectArray;
    
    @property(nonatomic, strong) NSMutableArray *textArray;
    @property(nonatomic, strong) NSMutableArray *textRectArray;
    
    @property(nonatomic, strong)  NSMutableData *data;
    
    + (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize;
    // i metodi vanno invocati nel seguente ordine:
    -(void)initContent;
    -(void)addImageWithRect:(UIImage*)image inRect:(CGRect)rect;
    -(void)addTextWithRect:(NSString*)text inRect:(CGRect)rect;
    -(void)addHeadertWithRect:(NSString *)text inRect:(CGRect)rect;
    
    - (void) drawText;
    - (void) drawHeader;
    - (void) drawImage;
    - (NSMutableData*) generatePdfWithFilePath: (NSString *)thefilePath;
    @end
    

    PDFHelper.m

    #import "PDF.h"
    
    @implementation PDF
    @synthesize size, imageArray, header, imageRectArray, textArray, textRectArray, data, headerRect;
    -(void)initContent{
        imageArray = [[NSMutableArray alloc]init];
        imageRectArray = [[NSMutableArray alloc]init];
    
        textArray = [[NSMutableArray alloc]init];
        textRectArray = [[NSMutableArray alloc]init];
    
        header = [[NSMutableArray alloc]init];
        headerRect = [[NSMutableArray alloc]init];
    
        data = [NSMutableData data];
      //  data = [NSMutableData data];
    
    }
    - (void) drawHeader
    {
        for (int i = 0; i < [header count]; i++) {
    
    
            CGContextRef    currentContext = UIGraphicsGetCurrentContext();
            CGContextSetRGBFillColor(currentContext, 0.0, 0.0, 0.0, 1.0);
    
            NSString *textToDraw = [header objectAtIndex:i];
    
    
            NSLog(@"Text to draw: %@", textToDraw);
            CGRect renderingRect = [[headerRect objectAtIndex:i]CGRectValue];
            NSLog(@"x of rect is %f",  renderingRect.origin.x);
    
    
            UIFont*font = [UIFont fontWithName:@"HelveticaNeue-Light" size:30.0];
    
            UIColor*color = [UIColor colorWithRed:255/255.0 green:79/255.0 blue:79/255.0 alpha:1.0];
            NSDictionary*att = @{NSFontAttributeName: font, NSForegroundColorAttributeName:color};
            NSStringDrawingContext *context = [NSStringDrawingContext new];
            context.minimumScaleFactor = 0.1;
            //        [textToDraw drawInRect:renderingRect withAttributes:att];
            [textToDraw drawWithRect:renderingRect options:NSStringDrawingUsesLineFragmentOrigin attributes:att context:context];
        }
    
    }
    -(void)drawImage{
        for (int i = 0; i < [imageArray count]; i++) {
            [[imageArray objectAtIndex:i] drawInRect:[[imageRectArray objectAtIndex:i]CGRectValue]];
    
        }
    }
    - (void) drawText
    {
        for (int i = 0; i < [textArray count]; i++) {
    
    
        CGContextRef    currentContext = UIGraphicsGetCurrentContext();
        CGContextSetRGBFillColor(currentContext, 0.0, 0.0, 0.0, 1.0);
    
        NSString *textToDraw = [textArray objectAtIndex:i];
    
    
            NSLog(@"Text to draw: %@", textToDraw);
            CGRect renderingRect = [[textRectArray objectAtIndex:i]CGRectValue];
            NSLog(@"x of rect is %f",  renderingRect.origin.x);
    
    
            UIFont*font = [UIFont fontWithName:@"HelveticaNeue-Light" size:22.0];
    
            UIColor*color = [UIColor blackColor];
            NSDictionary*att = @{NSFontAttributeName: font, NSForegroundColorAttributeName:color};
    
    
            [textToDraw drawWithRect:renderingRect options:NSStringDrawingUsesLineFragmentOrigin attributes:att context:nil];
    }
    
    }
    + (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize {
        //UIGraphicsBeginImageContext(newSize);
        UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);
        [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
        UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();    
        UIGraphicsEndImageContext();
        return newImage;
    }
    -(void)addImageWithRect:(UIImage *)image inRect:(CGRect)rect{
        UIImage *newImage = [PDF imageWithImage:image scaledToSize:CGSizeMake(rect.size.width, rect.size.height)];
    
    
        [imageArray addObject:newImage];
        [imageRectArray addObject:[NSValue valueWithCGRect:rect]];
    }
    -(void)addTextWithRect:(NSString *)text inRect:(CGRect)rect{
        [textArray addObject:text];
        [textRectArray addObject:[NSValue valueWithCGRect:rect]];
    }
    -(void)addHeadertWithRect:(NSString *)text inRect:(CGRect)rect{
        [header addObject:text];
        [headerRect addObject:[NSValue valueWithCGRect:rect]];
    }
    
    - (NSMutableData*) generatePdfWithFilePath: (NSString *)thefilePath
    {
    
        UIGraphicsBeginPDFContextToFile(thefilePath, CGRectZero, nil);
    
    
        BOOL done = NO;
        do 
        {
            //Start a new page.
            UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, size.width, size.height), nil);
    
            //Draw Header
            [self drawHeader];
            //Draw Text
            [self drawText];
            //Draw an image
            [self drawImage];
    
            done = YES;
        } 
        while (!done);
    
        // Close the PDF context and write the contents out.
        UIGraphicsEndPDFContext();
    
    
        //For data    
        UIGraphicsBeginPDFContextToData(data, CGRectZero, nil);
    
    
        BOOL done1 = NO;
        do 
        {
            //Start a new page.
            UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, size.width, size.height), nil);
    
            //Draw Header
            [self drawHeader];
            //Draw Text
            [self drawText];
            //Draw an image
            [self drawImage];
    
            done1 = YES;
        } 
        while (!done1);
    
        // Close the PDF context and write the contents out.
        UIGraphicsEndPDFContext();
        return data;
    }
    

    Now import the PDf.h in the class and use something like this to create and draw your pdf:

    -(void)CreaPDFconPath:(NSString*)pdfFilePath{
    
    
        UIFont*font = [UIFont fontWithName:@"HelveticaNeue-Light" size:22.0];
    
        UIColor*color = [UIColor blackColor];
        NSDictionary*att = @{NSFontAttributeName: font, NSForegroundColorAttributeName:color};
    
        NSString* text = [NSString stringWithFormat:@"%@ \n\n%@", self.ingredienti.text, self.preparazione.text];
    
        CGFloat stringSize = [text boundingRectWithSize:CGSizeMake(980, CGFLOAT_MAX)// use CGFLOAT_MAX to dinamically calculate the height of a string
                                                options:NSStringDrawingUsesLineFragmentOrigin
                                             attributes:att context:nil].size.height;
    
        //creo pdf e vi aggiungo testo e immagini
        PDF*pdfFile = [[PDF alloc]init];
        [pdfFile initContent];
        [pdfFile setSize:CGSizeMake(1000, 400+stringSize)];
    
        [pdfFile addHeadertWithRect:self.fieldNome.text inRect:CGRectMake(10, 10, 980, 60)];
    
        [pdfFile addImageWithRect:self.image.image inRect:CGRectMake(10, 80, 250, 250)];
    
        NSString*stringInfo = [NSString stringWithFormat:@"%@:%@ \n\n%@",self.oreCottura.text,self.minutiDiCottura.text,self.numeroPersone.text];
        [pdfFile addHeadertWithRect:stringInfo inRect:CGRectMake(300, 190, 500, 120)];
    
        [pdfFile addTextWithRect:text inRect:CGRectMake(10, 350, 980, CGFLOAT_MAX)];
    
    
        //disegno header immagine e testo
        [pdfFile drawHeader];
        [pdfFile drawImage];
        [pdfFile drawText];
        //genero pdf
        [pdfFile generatePdfWithFilePath:pdfFilePath];
    }