1

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

[[QLPreviewPanel sharedPreviewPanel] makeKeyAndOrderFront:nil];

这完成了它的工作,并显示空白的快速查看面板,上面写着“未选择项目”。在网上做了一些研究后,我实现了一个自定义的 NSTableView 子类作为快速查看面板的委托和数据源。我收到 Quick Look 询问我是否想成为代表的通知,我回复“是”。即使我在 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

而且快速查看面板没有出现,我觉得这很奇怪。上面的第一行只是我知道单元格已被单击。无论如何,这是自定义表格视图子类的 .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

谢谢你的帮助。

4

2 回答 2

9

文档不是最好的,因为它是 10.6 中添加的新功能。(嗯,显然有类和协议参考,但根据我的经验,我总是发现配套指南更有助于理解对象在现实世界场景中的使用方式)。

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

QLPreviewPanelController 协议参考

Quick Look 预览面板显示由实现此协议中的方法的响应者链中的第一个对象提供的项目的预览。您通常在窗口控制器或委托中实现这些方法。如果您不控制面板,则永远不应尝试修改预览面板状态。

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

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

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

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

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

除了返回 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.");
}
于 2010-12-25T00:49:58.410 回答
3

第一的:

-acceptsPreviewPanelControl 应该只返回 YES 而不要尝试设置委托和数据源。

然后,问题是你得到一个打破面板的异常:

2010-12-24 15:32:18.291 BackMeUp[4763:80f]-[NSPathStore2 stringValue]:无法识别的选择器发送到实例 0x5ecb10

异常很可能是由这些调用引起的:

[[[self dataSource] tableView:self objectValueForTableColumn:fileColumn row:selectedRow] stringValue]

很可能, [[self dataSource] tableView:self objectValueForTableColumn:fileColumn row:selectedRow] 是文件路径(一个 NSPathStore 实例,它是 NSString 的子类),因此它不响应 -stringValue

所以替换:

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

经过:

[NSURL fileURLWithPath:[[self dataSource] tableView:self objectValueForTableColumn:fileColumn row:selectedRow]]

还要删除transitionImageForPreviewItem 中对-stringValue 的调用。

附带说明一下,在每次调用 transitionImageForPreviewItem 时加载图像似乎不是最理想的。我想您已经在其他地方计算了图像(显示在您的表格视图中),尝试使用它。

于 2010-12-25T00:47:43.277 回答