我最近一直在寻找一个很好的PDF教程,文档等等。
我最终使用了this代码,但问题很少。
方案
我有一个包含标签,textView和imageView的视图。
现在,我们将调用标签name
,textView description
和imageView 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];
}
它会显示在每个页面的开头。
现在我不知道如何在内容(描述)之后绘制图像!
任何帮助都非常感谢!
答案 0 :(得分:4)
在上下文中绘制pdf就像在画布中绘图一样。
绘制动态文本和图像的最佳方法是创建和使用绘制方法,返回用于在页面中绘制的高度,并简单地保留变量以通过递增计算下一个绘图orgin y位置返回值。还有一个单独的偏移量变量来检查页面框架。
要将图像绘制到pdf上下文中,您可以使用以下示例。您还可以通过Core Graphics渲染CGImage
,但是您必须考虑画布的旋转(CGContext
),因为那些因为Core Graphics中的坐标原点位于右下角,所以将以颠倒的方式显示(翻转)。
UIImage *gymLogo=[UIImage imageNamed:@"logo.png"];
CGPoint drawingLogoOrigin = CGPointMake(5,5);
[gymLogo drawAtPoint:drawingLogoOrigin];
快乐编码:)
答案 1 :(得分:1)
首先在pdf_tutorialViewController.h
文件
- (void)drawImage:(UIImage *)img atRect:(CGRect)rect inContext:(CGContextRef)ctx;
/////////////// pdf_tutorialViewController.m file //////////
并添加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];
}
此代码可能对您有所帮助:)
谢谢
答案 2 :(得分:1)
这里是UIView
的子类,可以做你想要的......
您可以将其放在UIScrollView
中。在超级浏览-sizeThatFits:
期间,请致电-layoutSubviews
以获取正确的框架尺寸。 (也适用于您的封闭滚动视图&#39> 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
<强> View.m 强>
#import "View.h"
@implementation UILabel (SizeThatFits)
-(CGSize)sizeThatFits:(CGSize)fitSize
{
return [ self.text sizeWithFont:self.font constrainedToSize:fitSize ] ;
}
@end
@interface View ()
@property ( nonatomic, strong, readonly ) UIImage * pdfImage ;
@end
@implementation View
@synthesize descriptionLabel = _descriptionLabel ;
@synthesize nameLabel = _nameLabel ;
@synthesize pdfImageView = _pdfImageView ;
@synthesize pdfImage = _pdfImage ;
-(void)dealloc
{
CGPDFDocumentRelease( _pdf ) ;
}
-(CGSize)sizeThatFits:(CGSize)size
{
CGSize fitSize = (CGSize){ size.width, CGFLOAT_MAX } ;
CGSize result = { size.width, 0 } ;
result.height = [ self.headerLabel sizeThatFits:fitSize ].height
+ [ self.label sizeThatFits:fitSize ].height
+ self.pdfImage.size.height * fitSize.width / self.pdfImage.size.width ;
return result ;
}
-(void)layoutSubviews
{
CGRect bounds = self.bounds ;
CGRect slice ;
CGRectDivide( bounds, &slice, &bounds, [ self.headerLabel sizeThatFits:bounds.size ].height, CGRectMinYEdge ) ;
self.headerLabel.frame = slice ;
CGRectDivide( bounds, &slice, &bounds, [ self.label sizeThatFits:bounds.size ].height, CGRectMinYEdge ) ;
self.label.frame = slice ;
self.pdfImageView.frame = bounds ;
}
-(void)setPdf:(CGPDFDocumentRef)pdf
{
CGPDFDocumentRelease( _pdf ) ;
_pdf = CGPDFDocumentRetain( pdf ) ;
_pdfImage = nil ;
}
-(UILabel *)descriptionLabel
{
if ( !_descriptionLabel )
{
UILabel * label = [[ UILabel alloc ] initWithFrame:CGRectZero ] ;
label.numberOfLines = 0 ;
//
// ... configure label here
//
[ self addSubview:label ] ;
_descriptionLabel = label ;
}
return _descriptionLabel ;
}
-(UILabel *)nameLabel
{
if ( !_nameLabel )
{
UILabel * label = [[ UILabel alloc ] initWithFrame:CGRectZero ] ;
label.numberOfLines = 0 ;
//
// ... configure label here
//
[ self addSubview:label ] ;
_nameLabel = label ;
}
return _nameLabel ;
}
-(UIView *)pdfImageView
{
if ( !_pdfImageView )
{
UIImageView * imageView = [[ UIImageView alloc ] initWithFrame:CGRectZero ] ;
[ self addSubview:imageView ] ;
_pdfImageView = imageView ;
}
return _pdfImageView ;
}
-(UIImage *)pdfImage
{
if ( !_pdfImage )
{
CGPDFPageRef page = CGPDFDocumentGetPage( self.pdf, 1 ) ; // 1 indexed
CGRect mediaBox = CGPDFPageGetBoxRect( page, kCGPDFMediaBox ) ;
UIGraphicsBeginImageContextWithOptions( mediaBox.size, NO, self.window.screen.scale ) ;
CGContextRef c = UIGraphicsGetCurrentContext() ;
CGContextScaleCTM( c, 1.0f, -1.0f ) ;
CGContextTranslateCTM( c, 0.0, -mediaBox.size.height ) ;
CGContextDrawPDFPage( c, page ) ;
_pdfImage = UIGraphicsGetImageFromCurrentImageContext() ;
self.pdfImageView.image = _pdfImage ;
UIGraphicsEndImageContext() ;
}
return _pdfImage ;
}
@end
如果您需要页码页脚,可以按照相同的模式在底部添加另一个UILabel。
答案 3 :(得分:0)
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();