我在QuickLook
的表格中实施NSView
功能时遇到一些问题。关于QuickLook
的有限文档确实没有任何帮助。
在阅读了Apple Docs(它们主要针对自定义生成器和插件)之后,我最终查看了QuickLookDownloader sample code。这段代码基于一个基于文档的应用程序,但对我来说似乎是正确的方法(毕竟它是Apple的代码,它确实在他们的项目中工作)。
在我的实施中,我可以让QuickLook panel
显示得很好,我可以轻松地解雇它。但是,面板本身从不在NSViewController
内调用委托方法。结果我甚至都没有显示对象,只是措辞“没有选择项目”。我很难过。
我试着打电话给setDelegate
,但如果我沿着那条路走下去,就会被警告即将到来的厄运......
[QL] QLError(): - [QLPreviewPanel setDelegate:]在面板没有控制器时调用 - 修复此问题或者很快就会出现这种情况。 请参阅QLPreviewPanel.h中的注释-acceptsPreviewPanelControl:/ - beginPreviewPanelControl:/ - endPreviewPanelControl:。
然后在尝试响应其中一个委托方法时,使用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(尽管我认为没有理由为什么它应该进入等式)?
任何和所有帮助都非常感激。
解决方案更新
感谢彼得的观察,修复很快。当调试器中的错误消息意味着什么时,你不讨厌它吗? : - )
在我加载MyViewController
的课程中,我只需要添加三行代码来解决问题。
// 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];
完成工作:-)谢谢Peter。
答案 0 :(得分:6)
如果您还没有代表,为什么还希望它向您发送委托消息?如果您希望它向您发送委托消息,那么您需要将自己设置为其委托。
我试着打电话给
setDelegate
,但如果我沿着那条路走下去,就会被警告即将到来的厄运......[QL]
QLError()
:-[QLPreviewPanel setDelegate:]
在面板没有控制器时调用 - 修复此问题,否则很快就会出现此问题。请参阅QLPreviewPanel.h中针对-acceptsPreviewPanelControl:
/-beginPreviewPanelControl:
/-endPreviewPanelControl:
的评论。
“没有控制器”,它说。所以,你需要它来拥有一个控制器。
关于该标题的注释,特别是acceptsPreviewPanelControl:
和QLPreviewPanel实例方法updateController
的注释,表明面板的控制器(如果有的话)是响应者链中的对象。因此,如果您的控制器没有成为面板的控制器,那是因为您的控制器不在响应器链中。
所以,解决这个问题,然后就可以了。
我认为只要视图或其任何子视图位于响应者链中,您的视图控制器就应该位于响应者链中,但可能情况并非如此。 The documentation没有说。如果所有其他方法都失败了,请将您自己设置为某个视图的下一个响应者(并将其上一个下一个响应者作为您的下一个响应者),然后向预览面板发送updateController
消息。
答案 1 :(得分:0)
经过这么多年,在迅速的世界中,我发现这行代码也行得通。 无需重新排列默认的响应链,只需“推”您的视图控制器成为窗口中的第一个响应者。我不确定它是否适用于每种情况:
@mark_db
对象设置相同:
view.window?.makeFirstResponder(self)