QuickLook消费者作为NSViewController的委托 [英] QuickLook consumer as a delegate from an NSViewController

查看:279
本文介绍了QuickLook消费者作为NSViewController的委托的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 NSView 中的表格中执行 QuickLook 功能方面的某些问题。 QuickLook 中的有限文件根本没有帮助。



阅读 Apple Docs (它们主要面向自定义生成器和插件),最后我看了一下 QuickLookDownloader示例代码。这个代码是基于一个基于文档的应用程序,但似乎对我来说是正确的方法(毕竟是苹果的代码,它在他们的项目中工作)。



在我的实现中,我可以得到 QuickLook面板显示出来,我可以很简单的解决它。但是,面板本身从来没有从我的 NSViewController 中调用委托方法。因此,我甚至不会显示对象,只是使用措辞没有项目选择。我试图调用一个 setDelegate ,但是如果我继续下去,就会警告即将到来的厄运路线...


[QL] QLError(): - 当面板没有控制器时调用的[QLPreviewPanel setDelegate:] - 修复此或这将很快提升。
请参阅QLPreviewPanel.h中的评论for -acceptsPreviewPanelControl:/ - beginPreviewPanelControl:/ - endPreviewPanelControl:。


然后,无论如何,当一个dealloc尝试回应其中一个代理方法时。



是的,我读了标题,确认我应该在我赢得代理之后设置代理面板(见下面的代码)。



所以这里是我的代码,它几乎与示例代码相匹配,除了a)我从哪里得到我的数据(我得到它来自 NSArrayController )和b)我从中获得我的预览项目(我的直接来自我的模型对象 - 或者反正)

  @interface MyViewController:NSViewController 
< QLPreviewPanelDataSource,QLPreviewPanelDelegate> {

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

// [...]其他实例vars
}

@implementation MyViewController

// [...]其他方法,init,dealloc等...

- (IBAction)togglePreviewPanel:(id)previewPanel {

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

- (BOOL)acceptPreviewPanelControl :( QLPreviewPanel *)面板
{
return YES;
}

//此文档现在负责预览面板。
//允许设置委托,数据源和刷新面板。

- (void)beginPreviewPanelControl :( QLPreviewPanel *)面板
{

if(DEBUG)NSLog(@QuickLook面板控件做了BEGIN);

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

//本文档在预览面板上失去其责任。
//直到下一次调用-beginPreviewPanelControl:它不能更改
//面板的委托,数据源或刷新它。

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

if(DEBUG)NSLog(@QuickLook面板控件做了END);
}

//快速查看面板数据源

- (NSInteger)numberOfPreviewItemsInPreviewPanel :( QLPreviewPanel *)面板
{

if(DEBUG)NSLog(@QuickLook预览计数调用);

return [[myArrayController selectedObjects] count];
}

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

if(DEBUG)NSLog(@QuickLook预览选择项目);

return [[displayAC selectedObjects] objectAtIndex:index];


- (BOOL)previewPanel :( QLPreviewPanel *)面板handleEvent:(NSEvent *)事件{

if(DEBUG)NSLog(@QuickLook面板名为)的错误处理程序;

//将所有键下拉事件重定向到表视图

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

return NO;
}

这个问题似乎是 acceptPreviewPanelControl 永远不会被调用,所以代理从来没有被使用(他们绝对不会被调用)。



我确定这是一个简单的步骤,但是在解剖了示例代码并扫描文档后,我没有看到答案。



是因为这是所有来自NSViewController内的(虽然我看到没有理由,甚至应该进入方程式)?



任何和所有的帮助非常感谢。



解决方案更新



感谢Peter的观察,修复是一个很快的修复。调试器中的错误信息意味着它说什么,你不是讨厌它吗? : - )



在我加载 MyViewController 的类中,我只需要添加三行代码即可解决问题

  // mainWindow是一个IBOutlet到我的窗口,因为调用类
//是一个简单的对象,而不是一个NSWindowController否则我可以
//使用`self`而不是`mainWindow`

NSResponder * aNextResponder = [mainWindow nextResponder];

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

工作完成:-)谢谢Peter。

解决方案

如果您还没有(代),您为什么期望它向您发送委托消息?如果你想要向你发送委托消息,那么你需要将自己设置为它的委托。


我尝试调用一个 setDelegate ,但是如果我继续沿着这条路线,就会得到警告。


[QL ] QLError() - [QLPreviewPanel setDelegate:] 调用时面板没有控制器 - 修复这个或这将很快加油在QLPreviewPanel.h中查看 -acceptsPreviewPanelControl的注释: / -beginPreviewPanelControl: / -endPreviewPanelControl:



无控制器,它说。所以,你需要它有一个控制器。



对该标题的评论,特别是在 acceptPreviewPanelControl:和QLPreviewPanel实例方法 updateController ,建议面板的控制器(如果有的话)是响应者链中的对象。因此,如果您的控制器不成为面板的控制器,那是因为您的控制器不在响应者链中。



所以,修复它,然后它会工作



我可以想象,当您的视图控制器的视图或其任何子视图位于响应者链中时,您的视图控制器应位于响应者链中,但也可能不是这样。 文档没有说。如果所有其他的都失败,请将您自己设置为某个视图的下一个响应者(及其先前的下一个响应者作为您的下一个响应者),然后将预览面板发送到 updateController 消息。


I am having some problems implementing QuickLook functionality from a table in an NSView. The limited documentation on QuickLook really doesn't help at all.

After reading through the Apple Docs (which are geared heavily towards custom generators and plugins), I ended up looking at the QuickLookDownloader sample code. This code is based upon a document-based application, but appears to be the right method for me (after all it is Apple's code and it does work in their project).

In my implementation I can get the QuickLook panel to show up just fine, and I can dismiss it just as easy. However, the panel itself never calls the delegate methods from within my NSViewController. As a result I never even get to displaying objects, just the wording "No items selected". And I am stumped.

I tried calling a setDelegate, but get warned about impending doom if I continue down that route...

[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:.

And then doom happens anyway with a dealloc when trying to respond to one of the delegate methods.

And yes I did read the header which confirms that I should be setting the delegate after I won the panel (see code below).

So here's my code, which pretty much matches the sample code with the exception of a) where I get my data from (I get it from an NSArrayController) and the b) where I get my preview item from (mine comes directly from my model object - or should anyway)

@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;
}

The issue seems to be that the acceptsPreviewPanelControl never gets called, so the delegates never get used (they definitely never get called).

I'm sure this is a simple step that I'm missing, but after dissecting the sample code and scouring over the docs I don't see the answer.

Is it because this is all from within an NSViewController (although I see no reason why that should even come into the equation)?

Any and all help much appreciated.

SOLUTION UPDATE

Thanks to Peter's observation, the fix was a quick one. Don't you hate it when the error message in the debugger means what it says? :-)

In my class that loaded MyViewController I simply needed to add three lines of code to fix the problem.

// 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];

Job done :-) Thanks Peter.

解决方案

Why would you expect it to send you delegate messages if you aren't (yet) its delegate? If you want it to send you delegate messages, then you need to set yourself as its delegate.

I tried calling a setDelegate, but get warned about impending doom if I continue down that route...

[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:.

"No controller", it says. So, you need it to have a controller.

The comments on that header, particularly on acceptsPreviewPanelControl: and the QLPreviewPanel instance method updateController, suggest that the panel's controller, when it has one, is an object that is in the responder chain. Therefore, if your controller is not becoming the panel's controller, it's because your controller isn't in the responder chain.

So, fix that, and then it'll work.

I would imagine that your view controller should be in the responder chain whenever its view or any subview thereof is in the responder chain, but maybe this isn't the case. The documentation doesn't say. If all else fails, set yourself as some view's next responder explicitly (and its previous next responder as your next responder), then send the preview panel an updateController message.

这篇关于QuickLook消费者作为NSViewController的委托的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆