Cocoa QuickLook由NSTableView Cell发起

Tri*_*ert 1 cocoa nstableview quicklook

我有一个包含2个不同列的NSTableView - 一个是显示文件图标的NSImageCell,第二个是NSTextFieldCell的自定义子类,其中包含文本右侧的快速查看按钮.单击"快速查看"按钮时,将调用以下代码:

[[QLPreviewPanel sharedPreviewPanel] makeKeyAndOrderFront:nil];
Run Code Online (Sandbox Code Playgroud)

这是它的工作,并显示空白的快速查看面板说"没有选择项目".在我对互联网进行了一些研究之后,我实现了一个自定义的NSTableView子类作为Quick Look面板的Delegate和Data Source.我收到Quick Look询问我是否想成为委托的通知,我回复YES.即使我在QLPreviewPanelDataSource和QLPreviewPanelDelegate中实现了所有方法,但在运行时我在控制台上收到此错误:

2010-12-24 15:32:17.235 BackMeUp[4763:80f] clicked: ~/Desktop/HUDTape.mov
2010-12-24 15:32:17.489 BackMeUp[4763:80f] [QL] QLError(): -[QLPreviewPanel setDelegate:] called while the panel has no controller - Fix this or this will raise soon.
See comments in QLPreviewPanel.h for -acceptsPreviewPanelControl:/-beginPreviewPanelControl:/-endPreviewPanelControl:.
2010-12-24 15:32:17.490 BackMeUp[4763:80f] [QL] QLError(): -[QLPreviewPanel setDataSource:] called while the panel has no controller - Fix this or this will raise soon.
See comments in QLPreviewPanel.h for -acceptsPreviewPanelControl:/-beginPreviewPanelControl:/-endPreviewPanelControl:.
2010-12-24 15:32:17.491 BackMeUp[4763:80f] We can now receive QL Events.
2010-12-24 15:32:18.291 BackMeUp[4763:80f] -[NSPathStore2 stringValue]: unrecognized selector sent to instance 0x5ecb10
2010-12-24 15:32:18.292 BackMeUp[4763:80f] -[NSPathStore2 stringValue]: unrecognized selector sent to instance 0x5ecb10
Run Code Online (Sandbox Code Playgroud)

并且Quick Look面板没有显示,我觉得很奇怪.上面的第一行就是我知道单元格被点击了.无论如何,这是自定义表视图子类的.m文件:

//
//  BackupListTableView.m
//  BackMeUp
//
//  Created by Tristan Seifert on 12/24/10.
//  Copyright 2010 24/7 Server. All rights reserved.
//

#import "BackupListTableView.h"


@implementation BackupListTableView

- (void) awakeFromNib {

}

// Quick Look Delegates

- (BOOL)acceptsPreviewPanelControl:(QLPreviewPanel *)panel;
{
    [QLPreviewPanel sharedPreviewPanel].delegate = self;
    [QLPreviewPanel sharedPreviewPanel].dataSource = self;

    NSLog(@"We can now receive QL Events.");

    return YES;
}

- (void)beginPreviewPanelControl:(QLPreviewPanel *)panel
{
    // This document is now responsible of the preview panel
    // It is allowed to set the delegate, data source and refresh panel.
    [QLPreviewPanel sharedPreviewPanel].delegate = self;
    [QLPreviewPanel sharedPreviewPanel].dataSource = self;
}

- (void)endPreviewPanelControl:(QLPreviewPanel *)panel
{
    // 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.
    return;
}

// Quick Look panel data source

- (NSInteger)numberOfPreviewItemsInPreviewPanel:(QLPreviewPanel *)panel
{
    return 1;
}

- (id <QLPreviewItem>)previewPanel:(QLPreviewPanel *)panel previewItemAtIndex:(NSInteger)index
{
    int selectedRow = [self selectedRow];


    return [NSURL URLWithString:[[[self dataSource] tableView:self objectValueForTableColumn:fileColumn row:selectedRow] stringValue]];
}

// Quick Look panel delegate

- (BOOL)previewPanel:(QLPreviewPanel *)panel handleEvent:(NSEvent *)event
{
    // redirect all key down events to the table view

    return NO;
}

// This delegate method provides the rect on screen from which the panel will zoom.
- (NSRect)previewPanel:(QLPreviewPanel *)panel sourceFrameOnScreenForPreviewItem:(id <QLPreviewItem>)item
{

    NSRect iconRect = [self rectOfColumn:1];
    /*
     // check that the icon rect is visible on screen
     NSRect visibleRect = [self visibleRect];


     // convert icon rect to screen coordinates
     iconRect = [self convertRectToBase:iconRect];
     iconRect.origin = [[self window] convertBaseToScreen:iconRect.origin];
     */
    return iconRect;
}

// This delegate method provides a transition image between the table view and the preview panel
- (id)previewPanel:(QLPreviewPanel *)panel transitionImageForPreviewItem:(id <QLPreviewItem>)item contentRect:(NSRect *)contentRect
{
    int selectedRow = [self selectedRow];

    NSImage *fileIcon = [[NSWorkspace sharedWorkspace] iconForFile:[[[self dataSource] tableView:self objectValueForTableColumn:fileColumn row:selectedRow] stringValue]];

    return fileIcon;
}

@end
Run Code Online (Sandbox Code Playgroud)

谢谢你的帮助.

NSG*_*God 8

文档不是最好的,因为它是10.6中添加的新功能.(嗯,显然有类和协议引用,但根据我的经验,我总是发现Companion Guides更有助于理解对象如何在真实场景中使用).

QLPreviewPanelController协议参考定义了3种方法:

QLPreviewPanelController协议参考

"快速查看"预览面板显示响应程序链中实现此协议中方法的第一个对象提供的项目的预览.您通常在窗口控制器或委托中实现这些方法.如果您不控制面板,则不应尝试修改预览面板状态.

- (BOOL)acceptsPreviewPanelControl:(QLPreviewPanel *)panel;

- (BOOL)beginPreviewPanelControl:(QLPreviewPanel *)panel;

- (void)endPreviewPanelControl:(QLPreviewPanel *)panel;

我猜你的代码应该是这样的:

- (BOOL)acceptsPreviewPanelControl:(QLPreviewPanel *)panel
{
    return YES;
}
Run Code Online (Sandbox Code Playgroud)

除了返回YES之外,你不应该在该方法中做任何事情.acceptsPreviewPanelControl:被发送到响应者链中的每个对象,直到某些东西返回YES.通过返回YES,该对象实际上变为"控制器".从第一个方法返回YES后,在控制器对象上调用后两个方法.因此,您应该只在方法中设置委托和数据源beginPreviewPanelControl:(此时您将被视为当前控制器).

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

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

    [QLPreviewPanel sharedPreviewPanel].delegate = self;
    [QLPreviewPanel sharedPreviewPanel].dataSource = self;

    NSLog(@"We can now receive QL Events.");
}
Run Code Online (Sandbox Code Playgroud)