Mac OS X:如何将多个NSView绘制成一个新的多页PDF?

Tod*_*orf 4 macos cocoa core-graphics quartz-2d

我有一个与图形相关的基于文档的Mac App.我的应用程序的文档可能有多个"页面".每个页面都有一个NSView"画布"对象.

我的应用程序有几个导出选项,它们作为返回NSData对象(然后写入磁盘)的方法实现.

我想在一个方法中实现PDF导出选项:

  1. 创建内存中的PDF
  2. 通过我的文档的画布视图循环并在内存PDF中的新页面中呈现每个视图
  3. 返回内存中的多页PDF作为 NSData

下面的代码是我目前正在尝试的.

我的文档中的每个页面都是800 x 600像素.

当我将结果NSData对象写入磁盘时,写操作成功,但磁盘上的文件以某种方式损坏.该文件无法在预览或我尝试过的任何其他应用程序中打开.

我究竟做错了什么?

NSMutableData *data = [NSMutableData data];
CGDataConsumerRef consumer = CGDataConsumerCreateWithCFData((CFMutableDataRef)data);

CGRect mediaBox = CGRectMake(0.0, 0.0, 800.0, 600.0);
CGContextRef ctx = CGPDFContextCreate(consumer, &mediaBox, NULL);
CFRelease(consumer);

NSGraphicsContext *gc = [NSGraphicsContext graphicsContextWithGraphicsPort:ctx flipped:NO];

for (NSView *canvas in myCanvases) {
    CGContextBeginPage(ctx, &mediaBox);
    CGContextSaveGState(ctx);

    [canvas displayRectIgnoringOpacity:mediaBox inContext:gc];

    CGContextRestoreGState(ctx);
    CGContextEndPage(ctx);
}

CGPDFContextClose(ctx); // UPDATE: this line was originally missing. see answer below
CGContextRelease(ctx);

...

NSError *err = nil;
if (![data writeToFile:s options:NSDataWritingAtomic error:&err]) {
    if (err) {
        NSLog(@"%@", err);
    }
}
Run Code Online (Sandbox Code Playgroud)

Tod*_*orf 5

OP在这里.我已经解决了这个问题.我错过了最后的电话CGPDFContextClose().

所以在发布上下文之前......

CGPDFContextClose(ctx);
CGContextRelease(ctx);
Run Code Online (Sandbox Code Playgroud)