Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Macos Mac OS X:如何将多个NSView绘制成新的多页PDF?_Macos_Cocoa_Core Graphics_Quartz 2d - Fatal编程技术网

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

Macos Mac OS X:如何将多个NSView绘制成新的多页PDF?,macos,cocoa,core-graphics,quartz-2d,Macos,Cocoa,Core Graphics,Quartz 2d,我有一个与图形相关的基于文档的Mac应用程序。我的应用程序文档可能有多个“页面”。每个页面都有一个NSView“canvas”对象 我的应用程序有几个导出选项,它们被实现为返回NSData对象(然后写入磁盘)的方法 我想用以下方法实现PDF导出选项: 创建内存中的PDF 循环浏览我的文档的画布视图,并在内存PDF中的新页面中呈现每个视图 将内存中的多页PDF作为NSData 下面的代码是我目前正在尝试的 我的文档中的每一页都是800 x 600像素 当我将生成的NSData对象写入磁盘时,写入操

我有一个与图形相关的基于文档的Mac应用程序。我的应用程序文档可能有多个“页面”。每个页面都有一个
NSView
“canvas”对象

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

我想用以下方法实现PDF导出选项:

  • 创建内存中的PDF
  • 循环浏览我的文档的画布视图,并在内存PDF中的新页面中呈现每个视图
  • 将内存中的多页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);
        }
    }
    

    在这里。我已经解决了这个问题。我错过了对
    CGPDFContextClose()
    的最后一次调用

    所以在发布上下文之前

    CGPDFContextClose(ctx);
    CGContextRelease(ctx);
    

    我发现这是一个非常有用的答案(并且对问题和答案都进行了投票!)。在将它翻译成Swift 3时出现了一些小问题,但这就像一个符咒,它将在iOS上工作

    let data = NSMutableData()
    guard let consumer = CGDataConsumer(data: data) else { Swift.print("Aargh - no CGDataConsumer"); return }
    var mediaBox = CGRect(x: 0, y: 0, width: 800, height: 600)
    guard let ctx = CGContext(consumer: consumer, mediaBox: &mediaBox, nil) else { Swift.print("Aargh - no CGContext"); return }
    
    //let gc = NSGraphicsContext(cgContext: ctx, flipped: false) 
    //I don't need the NS context, as my drawing routines just use CGContext
    
    for page in self.pages { // Array of page models
        ctx.beginPage(mediaBox: &mediaBox)
        ctx.saveGState()
        myDraw(page, context: ctx, options: []) // My routine
        ctx.restoreGState()
        ctx.endPage()
    }
    ctx.closePDF()
    do {
        try data.write(toFile: "/Users/grimxn/Test.pdf", options: .atomic)
    } catch {
        Swift.print("Aargh - failed to write output file")
    }
    

    你能发布一个十六进制转储文件,可能是第一个千字节的数据吗?为什么要导出到内存中的数据对象?为什么不直接导出到文件中呢?我想知道你是否可以在这方面给我一些建议:谢谢!真不敢相信这么简单,谢谢!我在这上面浪费了好几个小时,因为这个错误是在我开始在OS 10.10上混合NSString绘图(通过AppKit扩展)而不是在OS 10.9上混合NSString绘图时发生的,所以我在寻找更复杂的东西。而且它以前在没有关闭上下文的情况下工作了好几个月!