从 UIScrollView + iphone 生成 PDF
Posted
技术标签:
【中文标题】从 UIScrollView + iphone 生成 PDF【英文标题】:PDF Generation From UIScrollView + iphone 【发布时间】:2011-03-11 04:26:22 【问题描述】:我想生成一个 UIScrollView 的 pdf,其内容大小接近 320*2000。如果我使用当前图形图像上下文来捕获滚动视图层,那么它只会捕获滚动视图的可见部分,而不是该滚动视图的整个层。
我正在使用以下代码:
-(void)CreatePdf:(id)sender
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *saveDirectory = [paths objectAtIndex:0];
NSString *saveFileName = @"myPDF.pdf";
[self writePDFAma];
CGRect arect=CGRectMake(0, 0, 768, 1024);
CreatePDFFileAma(arect, nil);
-(void) writePDFAma
UIImage *image;
NSData *data;
UIAlertView *successAlert;
UIAlertView *failureAlert;
//
NSArray *documentPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
// // This should be our documents directory
NSString *saveDiirectory = [documentPath objectAtIndex:0];
// // Our PDF is named 'Example.pdf'
NSString *saveFileName = @"FormImage2.JPG";
// // Create the full path using our saveDirectory and saveFileName
NSString *finalPath = [saveDiirectory stringByAppendingPathComponent:saveFileName];
//NSLog(@"%@",finalPath);
CGSize asize=CGSizeMake(_scrollview.frame.size.width, _scrollview.frame.size.height);
//NSLog(@"%d..%d",mainViewAma.frame.size.width, mainViewAma.frame.size.height);
UIGraphicsBeginImageContext(asize);
[[_scrollview layer] renderInContext:UIGraphicsGetCurrentContext()];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
data = UIImageJPEGRepresentation(image, 1.0);
BOOL catch;
if(!catch)
if ([[NSFileManager defaultManager] createFileAtPath:finalPath contents:data attributes:nil])
successAlert = [[UIAlertView alloc] initWithTitle:@"Success" message:@"Doodle was successfully saved to the Photo Library." delegate:self cancelButtonTitle:@"Close" otherButtonTitles:nil];
//[successAlert show];
[successAlert release];
else
failureAlert = [[UIAlertView alloc] initWithTitle:@"Failure" message:@"Failed to save doodle to the Photo Library." delegate:self cancelButtonTitle:@"Close" otherButtonTitles:nil];
//[failureAlert show];
[failureAlert release];
void CreatePDFFileAma (CGRect pageRect, const char *filename)
// This code block sets up our PDF Context so that we can draw to it
//some code here
CGContextRef pdfContext;
CFURLRef url;
CFMutableDictionaryRef myDictionary = NULL;
NSArray *documentPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
// // This should be our documents directory
NSString *saveDirectory = [documentPath objectAtIndex:0];
// // Our PDF is named 'Example.pdf'
//NSString *saveFileName = @"PDFForm2.pdf";
// // Create the full path using our saveDirectory and saveFileName
NSString *finalPath = [saveDirectory stringByAppendingPathComponent:saveFileName];
NSURL * aurl=[[NSURL alloc]initFileURLWithPath:finalPath];
url=(CFURLRef)aurl;
// This dictionary contains extra options mostly for 'signing' the PDF
myDictionary = CFDictionaryCreateMutable(NULL, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
CFDictionarySetValue(myDictionary, kCGPDFContextTitle, CFSTR("AMA FORM PDF"));
CFDictionarySetValue(myDictionary, kCGPDFContextCreator, CFSTR("My Name2"));
// Create our PDF Context with the CFURL, the CGRect we provide, and the above defined dictionary
pdfContext = CGPDFContextCreateWithURL (url, &pageRect, myDictionary);
// Cleanup our mess
CFRelease(myDictionary);
CFRelease(url);
// Starts our first page
CGContextBeginPage (pdfContext, &pageRect);
// Draws a black rectangle around the page inset by 50 on all sides
CGContextStrokeRect(pdfContext, CGRectMake(50, 50, 768, 1024));
// This code block will create an image that we then draw to the page
CGImageRef image;
CGDataProviderRef provider;
CFURLRef pictureURL;
documentPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
// // This should be our documents directory
saveDirectory = [documentPath objectAtIndex:0];
NSString *saveFileName2 = @"FormImage2.JPG";
// // Create the full path using our saveDirectory and saveFileName
NSString *finalPath2 = [saveDirectory stringByAppendingPathComponent:saveFileName2];
NSURL * aurl2=[[NSURL alloc]initFileURLWithPath:finalPath2];
pictureURL=(CFURLRef)aurl2;
provider = CGDataProviderCreateWithURL (pictureURL);
CFRelease (pictureURL);
image = CGImageCreateWithJPEGDataProvider(provider, NULL, TRUE, kCGRenderingIntentDefault); //DataProvider (, NULL, true, kCGRenderingIntentDefault);
CGDataProviderRelease (provider);
CGContextDrawImage (pdfContext, CGRectMake(0, 0,768, 1024),image);
CGImageRelease (image);
CGContextEndPage (pdfContext);
// We are done with our context now, so we release it
CGContextRelease (pdfContext);
【问题讨论】:
【参考方案1】:嘿伙计们,我准备了一些代码库,使用网上提供的示例从 UIScrollView 创建 PDF 我们应该清楚两件事
1) 页数 2) 内容大小 滚动视图
我创建了一个内容大小(10 * 910)的滚动视图。所以它有 10 页。。这是为 iPad 准备的。
这里是代码库
- (void) createPDF
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *directroyPath = nil;
directroyPath = [documentsDirectory stringByAppendingPathComponent:@"PDF"];
NSString *filePath = [directroyPath stringByAppendingPathComponent:@"test.pdf"];
// check for the "PDF" directory
NSError *error;
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath])
else
[[NSFileManager defaultManager] createDirectoryAtPath:directroyPath
withIntermediateDirectories:NO
attributes:nil
error:&error];
CGContextRef pdfContext = [self createPDFContext:myScrollView.bounds path:(CFStringRef)filePath];
NSLog(@"PDF Context created");
for (int i = 0 ; i< 10 ; i++)
// page 1
CGContextBeginPage (pdfContext,nil);
//turn PDF upsidedown
CGAffineTransform transform = CGAffineTransformIdentity;
transform = CGAffineTransformMakeTranslation(0, (i+1) * 910);
transform = CGAffineTransformScale(transform, 1.0, -1.0);
CGContextConcatCTM(pdfContext, transform);
//Draw view into PDF
[myScrollView.layer renderInContext:pdfContext];
CGContextEndPage (pdfContext);
[myScrollView setContentOffset:CGPointMake(0, (i+1) * 910) animated:NO];
CGContextRelease (pdfContext);
- (CGContextRef) createPDFContext:(CGRect)inMediaBox path:(CFStringRef) path
CGContextRef myOutContext = NULL;
CFURLRef url;
url = CFURLCreateWithFileSystemPath (NULL, path,
kCFURLPOSIXPathStyle,
false);
if (url != NULL)
myOutContext = CGPDFContextCreateWithURL (url,
&inMediaBox,
NULL);
CFRelease(url);
return myOutContext;
【讨论】:
嗨,Nikesh,我试用了您的代码,但我创建的 pdf 显然已损坏,因为预览和 Acrobat 都无法打开它……您有什么想法吗? @UrbanSeifert 您是否使用 .pdf 文件扩展名命名了您的 pdf 文件名? @Nikesh..感谢您的代码。它工作得很好,但是有一个问题,因为我的页面没有改变,而不是显示的控制器也坏了。例如。我在第2页,有一个按钮,在第1页显示一半,在第2页显示一半。有什么解决办法吗? @Abha 你得到解决方案了吗?【参考方案2】:我想出了一个不同的解决方案:
-(NSData*)pdfDataFromTableViewContent
NSMutableData *pdfData = [NSMutableData data];
//The real size, not only the visible part
CGSize contentSize = self.tableView.contentSize;
CGRect tableViewRealFrame = self.tableView.frame;
//Size tableView to show the whole content
self.tableView.frame = CGRectMake(0, 0, contentSize.width, contentSize.height);
//Generate PDF (one page)
UIGraphicsBeginPDFContextToData(pdfData,self.tableView.frame, nil);
UIGraphicsBeginPDFPage();
[self.tableView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIGraphicsEndPDFContext();
//Resize frame
self.tableView.frame = tableViewRealFrame;
return pdfData;
调整框架大小以适应 scrollView 的全部内容,在 graphicsContext 中捕获它,调整框架大小。
上面的代码生成一页。 对于更多页面,我基本上使用这个:
//MultiPage
CGRect mediaBox = self.tableView.frame;
CGSize pageSize = CGSizeMake(self.view.frame.size.width, 800);
UIGraphicsBeginPDFContextToData(pdfData, CGRectZero, nil);
CGContextRef pdfContext = UIGraphicsGetCurrentContext();
NSInteger currentPage = 0;
BOOL done = NO;
do
UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0.0, pageSize.width, pageSize.height), nil);
CGContextTranslateCTM(pdfContext, 0, -(pageSize.height*currentPage));
[self.view.layer renderInContext:pdfContext];
if ((pageSize.height*(currentPage+1)) > mediaBox.size.height) done = YES;
else currentPage++;
while (!done);
UIGraphicsEndPDFContext();
【讨论】:
【参考方案3】:是否可以查看您的示例代码,我正在尝试做同样的事情。
你可以在这里发送源代码,谢谢你会非常慷慨 dott.marco@mac.com
无论如何,对于您的问题,这可能会有所帮助:
您捕获可见内容只是因为您的滚动视图的大小仅匹配可见内容,它应该是。在开始绘制代码之前,您需要调整滚动视图的大小以匹配您需要捕获的内容:
代码: self.scrollView.frame = CGRectMake(0, 0, "你的内容宽度", "你的内容高度"); 完成绘图后,请确保将滚动视图的大小调整为向后,在本例中为容器视图:
代码: self.scrollView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
【讨论】:
嗨,Marco,我尝试过执行您的逻辑,但它对我不起作用。以上是关于从 UIScrollView + iphone 生成 PDF的主要内容,如果未能解决你的问题,请参考以下文章
iphone- UIScrollview 对角线滑动意外行为
(iphone) uiscrollview 触摸。取消内容触摸并开始滚动