2

ビューのコンテンツをPDFファイルに保存しようとしています。表示されるコードは、NSViewから継承するクラス内にあります。

- (IBAction) savePDF: (id) sender
{
    __block NSSavePanel* panel=[NSSavePanel savePanel];
    [panel setAllowedFileTypes: [NSArray arrayWithObject: @"pdf"]];
    [panel beginSheetModalForWindow: [self window] completionHandler: ^(NSInteger result)
     {
         if(result==NSOKButton)
         {
             NSCAssert(panel!=nil,@"panel is nil");
             NSData* data=[self dataWithPDFInsideRect: [self bounds]];
             NSError* error;
             BOOL successful=[data writeToURL: [panel URL] options: 0 error: &error];
             if(!successful)
             {
                 NSAlert* alert=[NSAlert alertWithError: error];
                 [alert runModal];
             }
         }
     }];
    panel=nil;
}

メソッドはメニューでトリガーされます。
問題は、アサーションが失敗することです。

NSCAssert(panel!=nil,@"panel is nil");

NSSavePanelポインターを__blockと宣言した場合でも、なぜですか?

4

2 に答える 2

2

実際には、答えは__block指定子を削除することです。

私はそれを使って/使わずにあなたのコードを実行しました。アサートはそれで失敗し、それなしで動作します (__block指定子、つまり)。

さて、その理由に答えるために:

__block指定子は、ローカル変数ではなくグローバル/インスタンス変数用に作成されたと思いますが、間違っている可能性があります。


X'D ...何が私を襲ったのかわかりませんが、これをチェックしてください:

NSSavePanel* panel=[NSSavePanel savePanel];

[panel setAllowedFileTypes: [NSArray arrayWithObject: @"pdf"]];
[panel beginSheetModalForWindow: [self window] completionHandler: ^(NSInteger result)
 {
     if(result==NSOKButton)
     {
         dispatch_async(dispatch_get_main_queue(), ^{
             NSCAssert(panel!=nil,@"panel is nil");
             NSData* data=[self dataWithPDFInsideRect:[self bounds]];
             NSError* error;
             BOOL successful=[data writeToURL: [panel URL] options: 0 error: &error];
             if(!successful)
             {
                 NSAlert* alert=[NSAlert alertWithError: error];
                 [alert runModal];
             }
         });
     }
 }];
panel=nil;

これを GCD ブロックにラップして、メイン スレッドで描画することにしました。あなたのコードは見事に機能しています。ビューは期待どおりに PDF に描画されており、確認できます:D.

問題に関しては、それは非常に明白なようです。バックグラウンド スレッドで境界を呼び出して描画することは禁止されています。

楽しかったです、ありがとう:D

于 2012-08-05T03:09:02.270 に答える
1

解決策: 不明な理由で、まだ私には謎ですが、ビュー クラスに IBAction を作成すると、[自己境界] は常に NSZeroRect を返します。他のメソッド内では正しい値を返します。 NSSavePanel から __block 指定子を削除し、アプリ デリゲート クラスのメソッドを書き換えます (また、再バインドします)。

于 2012-08-05T12:44:34.727 に答える