4

グラフィック関連のドキュメントベースのMacアプリを持っています。アプリのドキュメントに複数の「ページ」が含まれている場合があります。各ページにはNSView「キャンバス」オブジェクトがあります。

NSData私のアプリには、オブジェクトを返す(ディスクに書き込まれる)メソッドとして実装されるいくつかのエクスポートオプションがあります。

次のような方法でPDFエクスポートオプションを実装したいと思います。

  1. インメモリPDFを作成します
  2. ドキュメントのキャンバスビューをループし、それぞれをメモリ内PDFの新しいページにレンダリングします
  3. メモリ内の複数ページのPDFをNSData

以下のコードは私が現在試しているものです。

私のドキュメントの各ページは800x600ピクセルです。

結果の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);
    }
}
4

2 に答える 2

5

ここでOP。私は問題を解決しました。への最後の呼び出しがありませんでしたCGPDFContextClose()

したがって、コンテキストをリリースする前に...

CGPDFContextClose(ctx);
CGContextRelease(ctx);
于 2012-05-03T21:08:54.937 に答える
0

私はこれが最も有用な答えだと思いました(そして質問と答えの両方でOPに賛成する必要がありました!)。それをSwift3に変換する際にいくつかの問題がありましたが、これは魅力のように機能し、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")
}
于 2017-04-13T08:41:19.493 に答える