转载:http://marshal.easymorse.com/archives/3533

iOS创建PDF文件

参考了官方文档:《PDF Document Creation, Viewing, and Transforming》

pdf文档在iOS中是通过Quartz 2D库提供的api来操作的。iOS有两个图形库:

  • Quartz 2D,是iOS原生的,简单易用,缺点是只有2D,仅限于iOS

  • OpenGL ES,是开放标准的,2D和3D均有

使用Quartz 2D绘图到任意图形上下文(graphics context)创建pdf文件是很容易的事情。这需要:

  • 指定pdf文件的位置

  • 设置pdf的图形上下文(graphics context)

写了个特别简单的示例,效果如下:

p_w_picpath

完整的代码如下:

-(void)createPdf{
   NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
   NSString *saveDirectory = [paths objectAtIndex:0];
   NSString *saveFileName = @”myPDF.pdf”;
   NSString *newFilePath = [saveDirectory stringByAppendingPathComponent:saveFileName];
   const char *filename = [newFilePath UTF8String];
   CGRect pageRect=CGRectMake(0, 0, 612, 792);
   // This code block sets up our PDF Context so that we can draw to it
   CGContextRef pdfContext;
   CFStringRef path;
   CFURLRef url;
   CFMutableDictionaryRef myDictionary = NULL;
   // Create a CFString from the filename we provide to this method when we call it
   path = CFStringCreateWithCString (NULL, filename,
                                     kCFStringEncodingUTF8);
   // Create a CFURL using the CFString we just defined
   url = CFURLCreateWithFileSystemPath (NULL, path,
                                        kCFURLPOSIXPathStyle, 0);
   CFRelease (path);
   // This dictionary contains extra options mostly for ‘signing’ the PDF
   myDictionary = CFDictionaryCreateMutable(NULL, 0,
                                            &kCFTypeDictionaryKeyCallBacks,
                                            &kCFTypeDictionaryValueCallBacks);
   CFDictionarySetValue(myDictionary, kCGPDFContextTitle, CFSTR(“My PDF File”));
   CFDictionarySetValue(myDictionary, kCGPDFContextCreator, CFSTR(“My Name”));
   // 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);
   // Done creating our PDF Context, now it’s time to draw to it
   // 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, pageRect.size.width – 100, pageRect.size.height – 100));
   // Adding some text on top of the p_w_picpath we just added
   CGContextSelectFont (pdfContext, “Helvetica”, 30, kCGEncodingMacRoman);
   CGContextSetTextDrawingMode (pdfContext, kCGTextFill);
   CGContextSetRGBFillColor (pdfContext, 0, 0, 0, 1);
   const char *text =  (char *)[@”Hello world” UTF8String];
   CGContextShowTextAtPoint (pdfContext, 260, 390, text, strlen(text));
   // End text
   // We are done drawing to this page, let’s end it
   // We could add as many pages as we wanted using CGContextBeginPage/CGContextEndPage
   CGContextEndPage (pdfContext);
   // We are done with our context now, so we release it
   CGContextRelease (pdfContext);
}

会在当前应用的Documents目录下创建一个myPDF.pdf文件,文件中只有一行字,Hello world。

以下这段:

// This dictionary contains extra options mostly for ‘signing’ the PDF
   myDictionary = CFDictionaryCreateMutable(NULL, 0,
                                            &kCFTypeDictionaryKeyCallBacks,
                                            &kCFTypeDictionaryValueCallBacks);
   CFDictionarySetValue(myDictionary, kCGPDFContextTitle, CFSTR(“My PDF File”));
   CFDictionarySetValue(myDictionary, kCGPDFContextCreator, CFSTR(“My Name”));

可以不用,是设置pdf文件的一些属性的,比如作者等,那么可以:

pdfContext = CGPDFContextCreateWithURL (url, &pageRect, nil);

写入pdf是从CGContextBeginPage 函数开始,到CGContextEndPage函数截至。然后需要释放context:CGContextRelease。

目前不完美的是有两条:

  1. 汉字乱码

  2. 有报错

对第一个,据说需要使用其他方法,需要用NSString,可以参考这个帖子:

http://www.cocoachina.com/bbs/read.php?tid-2111.html

有报错,如这样:

Thu Oct 14 13:28:43 Henzil-mato-iPad pdfDemo[2200] <Error>: FT_Load_Glyph failed: error 6.

大量的这样的error,虽然我只是写了一行文本。引发错误的是:

CGContextShowTextAtPoint (pdfContext, 260, 390, text, strlen(text));

屏蔽这行就不抱错了。

搜到这个帖子:

http://discussions.apple.com/thread.jspa?messageID=7820664

但是将字体调大也无法解决问题,我调大30问题依旧。

所幸目前写的项目是老外用的,中文不是问题,另外,日志虽然报错,但是能正常生成文档。等有时间再解决这两个问题。