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];
仕事は終わりました :-) ピーターに感謝します。