Ios 在PDF文件中的内容后绘制图像

Ios 在PDF文件中的内容后绘制图像,ios,objective-c,pdf,Ios,Objective C,Pdf,我最近一直在搜索一个好的PDF教程、文档等 我最终使用了代码,但问题很少 场景 我有一个包含标签、文本视图和图像视图的视图。 现在,我们将调用标签name、文本视图description和图像视图image 该名称用作标题 描述是非常多变的,它可以从2行到一些页面 图像应位于描述文本的末尾 我正在使用以下代码: - (void)generatePDF{ NSString *fileName = [NSString stringWithFormat:@"%@.pdf",nameString

我最近一直在搜索一个好的PDF教程、文档等

我最终使用了代码,但问题很少

场景

我有一个包含标签、文本视图和图像视图的视图。 现在,我们将调用标签
name
、文本视图
description
和图像视图
image

该名称用作标题

描述是非常多变的,它可以从2行到一些页面

图像应位于描述文本的末尾

我正在使用以下代码:

- (void)generatePDF{
    NSString *fileName = [NSString stringWithFormat:@"%@.pdf",nameString];
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *pdfFileName = [documentsDirectory stringByAppendingPathComponent:fileName];

    CFAttributedStringRef currentText = CFAttributedStringCreate(NULL,
                                                                 (CFStringRef)descriptionString, NULL);
    if (currentText) {
        CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(currentText);
        if (framesetter) {

            // Create the PDF context using the default page: currently constants at the size
            // of 612 x 792.
            UIGraphicsBeginPDFContextToFile(pdfFileName, CGRectZero, nil);

            CFRange currentRange = CFRangeMake(0, 0);
            NSInteger currentPage = 0;
            BOOL done = NO;

            do {
                // Mark the beginning of a new page.
                UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, kDefaultPageWidth,
                                                          kDefaultPageHeight), nil);
                [self drawHeader]
                // Draw a page number at the bottom of each page
                currentPage++;
                [self drawPageNumber:currentPage];

                // Render the current page and update the current range to
                // point to the beginning of the next page.
                currentRange = [self renderPage:currentPage withTextRange:
                                currentRange andFramesetter:framesetter];

                // If we're at the end of the text, exit the loop.
                if (currentRange.location == CFAttributedStringGetLength
                    ((CFAttributedStringRef)currentText))
                    done = YES;
            } while (!done);

            // Close the PDF context and write the contents out.
            UIGraphicsEndPDFContext();

            // Release the framewetter.
            CFRelease(framesetter);

        } else {
            NSLog(@"Could not create the framesetter needed to lay out the atrributed string.");
        }
        // Release the attributed string.
        CFRelease(currentText);
    } else {
        NSLog(@"Could not create the attributed string for the framesetter");
    }

}

- (CFRange)renderPage:(NSInteger)pageNum withTextRange:(CFRange)currentRange
       andFramesetter:(CTFramesetterRef)framesetter
{
    // Get the graphics context.
    CGContextRef    currentContext = UIGraphicsGetCurrentContext();

    // Put the text matrix into a known state. This ensures
    // that no old scaling factors are left in place.
    CGContextSetTextMatrix(currentContext, CGAffineTransformIdentity);

    // Create a path object to enclose the text. Use 72 point
    // margins all around the text.
    CGRect    frameRect = CGRectMake(22,72, 468, 648);
    CGMutablePathRef framePath = CGPathCreateMutable();
    CGPathAddRect(framePath, NULL, frameRect);

    // Get the frame that will do the rendering.
    // The currentRange variable specifies only the starting point. The framesetter
    // lays out as much text as will fit into the frame.
    CTFrameRef frameRef = CTFramesetterCreateFrame(framesetter, currentRange, framePath, NULL);
    CGPathRelease(framePath);

    // Core Text draws from the bottom-left corner up, so flip
    // the current transform prior to drawing.
    CGContextTranslateCTM(currentContext, 0, kDefaultPageHeight);
    CGContextScaleCTM(currentContext, 1.0, -1.0);

    // Draw the frame.
    CTFrameDraw(frameRef, currentContext);

    // Update the current range based on what was drawn.
    currentRange = CTFrameGetVisibleStringRange(frameRef);
    currentRange.location += currentRange.length;
    currentRange.length = 0;
    CFRelease(frameRef);

    return currentRange;
}


- (void)drawPageNumber:(NSInteger)pageNum
{
    NSString* pageString = [NSString stringWithFormat:NSLocalizedString(@"Page", nil), pageNum];
    UIFont* theFont = [UIFont systemFontOfSize:12];
    CGSize maxSize = CGSizeMake(kDefaultPageWidth, 72);

    CGSize pageStringSize = [pageString sizeWithFont:theFont
                                   constrainedToSize:maxSize
                                       lineBreakMode:UILineBreakModeClip];
    CGRect stringRect = CGRectMake(((kDefaultPageWidth - pageStringSize.width) / 2.0),
                                   720.0 + ((72.0 - pageStringSize.height) / 2.0) ,
                                   pageStringSize.width,
                                   pageStringSize.height);

    [pageString drawInRect:stringRect withFont:theFont];
}
我想知道如何在页面的末尾,在描述的结尾之后绘制图像

我这样画标题:

-(void)drawHeader{
    NSString *headerString = nameString;
    UIFont* theFont = [UIFont boldSystemFontOfSize:15];
    CGSize maxSize = CGSizeMake(kDefaultPageWidth, 72);

    CGSize pageStringSize = [headerString sizeWithFont:theFont constrainedToSize:maxSize lineBreakMode:UILineBreakModeClip];
    CGRect stringRect = CGRectMake(22,22,pageStringSize.width,pageStringSize.height);

    [headerString drawInRect:stringRect withFont:theFont];
}
它会显示在每一页的开头

现在我不知道如何在内容(描述)之后绘制图像


非常感谢您的帮助

在上下文中绘制pdf就像在画布中绘制一样

绘制本质上是动态的文本和图像的最佳方法是创建和使用绘制方法,该方法返回用于在页面中绘制的高度,并简单地保留一个变量,通过增加返回值来计算下一个绘制组织位置。还可以放置一个单独的偏移变量来检查页面框架

为了将图像绘制到PDF上下文中,可以使用下面的示例。您还可以通过核心图形绘制<代码> CGImage <代码>,但是您必须考虑画布的旋转(<代码> cgValue),因为那些在核心图形的坐标原点位于右下角上(翻转)出现。

UIImage *gymLogo=[UIImage imageNamed:@"logo.png"];
CGPoint drawingLogoOrigin = CGPointMake(5,5);
[gymLogo drawAtPoint:drawingLogoOrigin];

快乐编码:)

首先在
pdf\u tutorialViewController.h
文件中创建自定义方法

- (void)drawImage:(UIImage *)img  atRect:(CGRect)rect inContext:(CGContextRef)ctx;
///////////////pdf\u tutorialViewController.m文件//////////

并添加
UIImage
并在方法的末尾调用
drawImage:atRect:inContext:
方法

- (CFRange)renderPage:(NSInteger)pageNum withTextRange:(CFRange)currentRange
       andFramesetter:(CTFramesetterRef)framesetter
{
  ////////////////////////////////////////////////////////////////////////////////////
       UIImage *logoimg = [UIImage imageNamed:@"1.png"];
       [self drawImage:logoimg atRect:CGRectMake("Your Size") inContext:currentContext];
       return currentRange;
  ////////////////////////////////////////////////////////////////////////////////////
} 
并添加代码

- (void)drawImage:(UIImage *)img  atRect:(CGRect)rect inContext:(CGContextRef)ctx
{
    UIImage *myImage = (UIImage *)img;
    [myImage drawInRect:rect];
    //[myImage release];
}
此代码可能对您有所帮助:)

- (void)drawImage:(UIImage *)img  atRect:(CGRect)rect inContext:(CGContextRef)ctx
{
    UIImage *myImage = (UIImage *)img;
    [myImage drawInRect:rect];
    //[myImage release];
}

谢谢

这里是
UIView
的一个子类,它可以满足您的需要

- (void)drawImage:(UIImage *)img  atRect:(CGRect)rect inContext:(CGContextRef)ctx
{
    UIImage *myImage = (UIImage *)img;
    [myImage drawInRect:rect];
    //[myImage release];
}
您可以将其放置在
UIScrollView
中。调用
-sizeThatFits:
在superview的
-layoutSubview中获取正确的帧大小。(也适用于封闭滚动视图的contentSize。)

请注意,我在UILabel上包含了一个类别,它将合理的大小返回到
-sizeThatFits:
,您可能希望提供自己的实现

View.h

#import <UIKit/UIKit.h>

@interface View : UIView
@property ( nonatomic, strong, readonly ) UILabel * descriptionLabel ;
@property ( nonatomic, strong, readonly ) UILabel * nameLabel ;
@property ( nonatomic, strong, readonly ) UIImageView * pdfImageView ;

@property ( nonatomic ) CGPDFDocumentRef pdf ;

@end

如果您需要页码页脚,您可以按照相同的模式在底部添加另一个UILabel。

试试这个&谢谢您的回答!这是我第一次使用CoreText,我仍然对它感到困惑!我会试试那个方法,但我总是要手动绘制CGPoint?我的意思是,我知道你提到了绘图+变量的事情,但我不知道在内容之后怎么做!我可以在-(CFRange)renderPage:(NSInteger)pageNum和textrange:(CFRange)currentRange和framesetter:(CTFramesetterRef)framesetter方法中执行吗?或者,如果我想在标题和内容之后绘制图像,可能吗?一个很好的pdf教程:是的,你可以将图像放置在任何你想要的地方,但诀窍在于如何设置图像的框架。这个问题也是:它们没有旋转,而是垂直翻转(镜像)谢谢你的回答!然后,在CGRectMake(“您的尺码”),问题是我不知道该放入哪个尺码,因为描述非常多变!有办法吗?因为现在图像出现在每个页面上,所以我希望它只出现在页面的末尾,即描述内容的结尾
CGRectMake(200,55,200,300)
使用它时,它的坐标似乎与文本重叠,加上它是颠倒的!:\然后把
CGRectMake(“根据需要”)
,因为我不知道…你的文本的结尾在哪里。谢谢你的回答!昨天我试过了,我发现如果在语句后面加上一个[self drawImage],那么最后可以很容易地画出图像如果(currentRange.location==CFAttributedStringGetLength((CFAttributedStringRef)currentText)),我会试试你的版本,我会让你知道的!不管你觉得哪个更容易--我喜欢这个,因为它只有3个子视图。。。表现也应该很好。如果您想要多个页面,只需创建多个视图。谢谢!我会让你知道的!:)谢谢你的时间
NSString *fileName = @"myInfo.pdf";
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *pdfFileName = [documentsDirectory stringByAppendingPathComponent:fileName];

if ([passwordString length]) {
    NSDictionary *dictionary = [[NSDictionary alloc] initWithObjectsAndKeys:passwordString, kCGPDFContextOwnerPassword, passwordString, kCGPDFContextUserPassword, kCFBooleanFalse, kCGPDFContextAllowsCopying, kCFBooleanFalse, kCGPDFContextAllowsPrinting,  nil]; // Providing Password Protection for PDF File
    UIGraphicsBeginPDFContextToFile(pdfFileName, CGRectZero, dictionary);
    [dictionary release];
} else {
    UIGraphicsBeginPDFContextToFile(pdfFileName, CGRectZero, nil);
}

UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, 612.0, heightOfView), nil); //612,792 Width  & Height of the pdf page which we want to generate.
NSString *pngPath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%d.png", 123]];
UIImage *pngImage = [UIImage imageWithContentsOfFile:pngPath];

[pngImage drawInRect:CGRectMake((612 - self.frame.size.width) / 2, 0, self.frame.size.width, heightOfView)]; // Size of the image we want to draw in pdf file.
UIGraphicsEndPDFContext();