10

QuickLookのテーブルから機能を実装する際に問題が発生していますNSView。に関する限られたドキュメントは、QuickLook実際にはまったく役に立ちません。

Apple Docs (カスタム ジェネレーターとプラグインに重点を置いています) を読んだ後、 QuickLookDownloader サンプル コードを調べました。このコードはドキュメントベースのアプリケーションに基づいていますが、私にとっては正しい方法のようです (結局のところ、これは Apple のコードであり、彼らのプロジェクトで機能します)。

私の実装では、 がQuickLook panel問題なく表示され、同じように簡単に閉じることができます。ただし、パネル自体が my 内からデリゲート メソッドを呼び出すことはありませんNSViewController。その結果、「アイテムが選択されていません」という文言だけで、オブジェクトを表示することさえできません。そして、私は困惑しています。

に電話してみsetDelegateましたが、そのルートを進むと差し迫った破滅について警告されます...

[QL] QLError(): - [QLPreviewPanel setDelegate:] が呼び出されたときに、パネルにコントローラーがありません - これを修正しないと、すぐに発生します。-acceptsPreviewPanelControl:/-beginPreviewPanelControl:/-endPreviewPanelControl: については、QLPreviewPanel.h のコメントを参照してください。

そして、いずれにせよ、デリゲート メソッドの 1 つに応答しようとすると、dealloc で破滅が起こります。

はい、パネルを獲得した後にデリゲートを設定する必要があることを確認するヘッダーを読みました(以下のコードを参照)。

これはサンプル コードとほぼ一致しますが、例外として、a) データを取得する場所 (からデータを取得するNSArrayController) と、b) プレビュー アイテムを取得する場所 (私のモデル オブジェクトから直接取得する場所) が異なります。 - またはとにかくする必要があります)

@interface MyViewController : NSViewController 
    <QLPreviewPanelDataSource, QLPreviewPanelDelegate> {

    QLPreviewPanel * previewPanel;
    NSArrayController * myArrayController;
    NSTableView * myTable;

    // [...] Other instance vars
}

@implementation MyViewController

// [...] all the other methods, init, dealloc etc...

-(IBAction)togglePreviewPanel:(id)previewPanel {

    if ([QLPreviewPanel sharedPreviewPanelExists] && 
          [[QLPreviewPanel sharedPreviewPanel] isVisible])
    {
       [[QLPreviewPanel sharedPreviewPanel] orderOut:nil];
    }
    else
    {
       [[QLPreviewPanel sharedPreviewPanel] makeKeyAndOrderFront:nil];
    }
 }

 -(BOOL)acceptsPreviewPanelControl:(QLPreviewPanel *)panel
 {    
      return YES;
 }

 // This document is now responsible of the preview panel. 
 // It is allowed to set the delegate, data source and refresh panel.

 -(void)beginPreviewPanelControl:(QLPreviewPanel *)panel 
 {

    if (DEBUG) NSLog(@"QuickLook panel control did BEGIN");

    previewPanel = [panel retain];
    panel.delegate = self;
    panel.dataSource = self;
 }

 // This document loses its responsisibility on the preview panel. 
 // Until the next call to -beginPreviewPanelControl: it must not change 
 // the panel's delegate, data source or refresh it.

 -(void)endPreviewPanelControl:(QLPreviewPanel *)panel   
 {
     [previewPanel release];
     previewPanel = nil;

     if (DEBUG) NSLog(@"QuickLook panel control did END");
 }

 // Quick Look panel data source

 -(NSInteger)numberOfPreviewItemsInPreviewPanel:(QLPreviewPanel *)panel 
 {

     if (DEBUG) NSLog(@"QuickLook preview count called");

     return [[myArrayController selectedObjects] count];
 }

 -(id <QLPreviewItem>)previewPanel:(QLPreviewPanel *)panel
        previewItemAtIndex:(NSInteger)index
 {

     if (DEBUG) NSLog(@"QuickLook preview selection of item called");

     return [[displayAC selectedObjects] objectAtIndex:index];
 }

 -(BOOL)previewPanel:(QLPreviewPanel *)panel handleEvent:(NSEvent *)event {

    if (DEBUG) NSLog(@"QuickLook panel error handler called");

// redirect all key down events to the table view

    if ([event type] == NSKeyDown) {
        [myTable keyDown:event];
    return YES;
    }

    return NO;
}

問題は、acceptsPreviewPanelControlが呼び出されないため、デリゲートが使用されないことです (絶対に呼び出されません)。

これは私が見逃している単純なステップだと確信していますが、サンプル コードを分析し、ドキュメントを精査した後、答えがわかりません。

これはすべて NSViewController 内からのものであるためですか (ただし、それが方程式に含まれる理由はわかりません)。

ありとあらゆる助けが大歓迎です。

ソリューションの更新

Peter の観察のおかげで、修正は迅速に行われました。デバッガーのエラー メッセージが意味することを嫌いませんか? :-)

ロードされた私のクラスでMyViewControllerは、問題を修正するために 3 行のコードを追加するだけで済みました。

// mainWindow is an IBOutlet to my window because the calling class 
// is a simple object and not an NSWindowController otherwise I could
// have used `self` instead of `mainWindow`

NSResponder * aNextResponder = [mainWindow nextResponder];

[mainWindow setNextResponder:myViewControllerInstance];
[myViewControllerInstance setNextResponder:aNextResponder];

仕事は終わりました :-) ピーターに感謝します。

4

2 に答える 2

7

(まだ) デリゲートでないのに、デリゲート メッセージを送信することを期待するのはなぜですか? 委任メッセージを送信する場合は、自分自身を委任として設定する必要があります。

に電話してみsetDelegateましたが、そのルートを進むと差し迫った破滅について警告されます...

[QL] QLError():-[QLPreviewPanel setDelegate:]パネルにコントローラーがないときに呼び出されます - これを修正しないと、すぐに発生します。-acceptsPreviewPanelControl:/ -beginPreviewPanelControl:/については、QLPreviewPanel.h のコメントを参照してください-endPreviewPanelControl:

「コントローラーなし」と表示されます。そのため、コントローラーが必要です。

そのヘッダーのコメント、特にacceptsPreviewPanelControl:QLPreviewPanel インスタンス メソッドのコメントupdateControllerは、パネルのコントローラーがある場合、そのコントローラーがレスポンダー チェーンにあるオブジェクトであることを示唆しています。したがって、コントローラーがパネルのコントローラーにならない場合は、コントローラーがレスポンダー チェーンに含まれていないことが原因です。

それで、それを修正してください、そうすればうまくいくでしょう。

ビューまたはそのサブビューがレスポンダーチェーンにあるときはいつでも、ビューコントローラーがレスポンダーチェーンにあるはずだと思いますが、そうではないかもしれません。ドキュメントは言いません。他のすべてが失敗した場合は、ビューの次のレスポンダーとして自分自身を明示的に設定し (およびその前の次のレスポンダーを次のレスポンダーとして)、プレビュー パネルにupdateControllerメッセージを送信します。

于 2010-10-01T15:17:29.160 に答える