2010-10-01 9 views
9

Tengo algunos problemas para implementar la funcionalidad QuickLook de una tabla en un NSView. La documentación limitada en QuickLook realmente no ayuda en absoluto.Consumidor QuickLook como delegado de NSViewController

Después de leer el Apple Docs (que están muy orientados a generadores personalizados y complementos), terminé mirando el QuickLookDownloader sample code. Este código se basa en una aplicación basada en documentos, pero parece ser el método correcto para mí (después de todo, es el código de Apple y funciona en su proyecto).

En mi implementación puedo obtener el QuickLook panel para mostrarme bien, y puedo descartarlo igual de fácil. Sin embargo, el panel nunca llama a los métodos de delegado desde mi NSViewController. Como resultado, nunca llegué a mostrar objetos, solo la fraseología "No hay elementos seleccionados". Y estoy perplejo.

Traté de llamar a un setDelegate, pero conseguir advertido sobre la destrucción inminente si sigo por ese camino ...

[QL] QLError(): - [QLPreviewPanel setDelegate:] llamada mientras que el panel no tiene Controlador: corrige esto o esto aumentará pronto. Ver comentarios en QLPreviewPanel.h para -acceptsPreviewPanelControl:/- beginPreviewPanelControl:/- endPreviewPanelControl :.

Y luego, la fatalidad ocurre de todos modos con un dealloc cuando se intenta responder a uno de los métodos delegados.

Y sí, leí el encabezado que confirma que debería establecer el delegado después de ganar el panel (ver código a continuación).

Así que aquí está mi código, que coincide con el código de muestra a excepción de a) de donde obtengo mis datos (lo obtengo de un NSArrayController) yb) de donde obtengo mi artículo de vista previa (el mío viene directamente de mi modelo de objetos - o debería de todos modos)

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

el problema parece ser que el acceptsPreviewPanelControl no es llamado, por lo que los delegados no se acostumbre (que sin duda nunca se llaman).

Estoy seguro de que este es un paso simple que me falta, pero después de diseccionar el código de muestra y recorrer los documentos no veo la respuesta.

¿Es porque todo esto es desde dentro de un NSViewController (aunque no veo ninguna razón por la que eso deba incluirse en la ecuación)?

Cualquier y toda ayuda muy apreciada.

SOLUCIÓN DE ACTUALIZACIÓN

Gracias a la observación de Pedro, el arreglo fue una rápida. ¿No lo odias cuando el mensaje de error en el depurador significa lo que dice? :-)

En mi clase que cargó MyViewController simplemente necesité agregar tres líneas de código para solucionar el problema.

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

Trabajo realizado :-) Thanks Peter.

Respuesta

6

¿Por qué esperas que te envíe mensajes de delegado si no eres (todavía) su delegado? Si desea que le envíe mensajes de delegado, entonces debe establecerse como su delegado.

Traté de llamar a un setDelegate, pero conseguir advertido sobre la destrucción inminente si sigo por ese camino ...

[QL] QLError(): -[QLPreviewPanel setDelegate:] llamada mientras que el panel tiene controlador - Solucionar este o esto aumentará pronto. Consulte los comentarios en QLPreviewPanel.h para -acceptsPreviewPanelControl:/-beginPreviewPanelControl:/-endPreviewPanelControl:.

"No controlador", dice. Entonces, necesitas que tenga un controlador.

Los comentarios sobre esa cabecera, particularmente en acceptsPreviewPanelControl: y el método de instancia QLPreviewPanel updateController, sugieren que el controlador del panel, cuando se tiene una, es un objeto que se encuentra en la cadena de respuesta. Por lo tanto, si su controlador no se está convirtiendo en el controlador del panel, es porque su controlador no está en la cadena de respuesta.

Así que, soluciona eso, y luego funcionará.

Me imagino que su controlador de vista debería estar en la cadena de respuesta siempre que su vista o cualquier subvista de la misma esté en la cadena de respuesta, pero tal vez este no sea el caso. The documentation no dice. Si todo lo demás falla, configúrese usted mismo como el siguiente respondedor de una vista de forma explícita (y su próximo respondedor anterior como su próximo respondedor), luego envíe un mensaje al updateController en el panel de vista previa.

+0

Como siempre, Peter su observación fue el error en mis formas. Había pasado por alto la idea de que NSViewController necesita agregarse a la cadena de respuesta (a diferencia de un controlador de ventana que se incluye automáticamente). ¡3 líneas de código y el problema se soluciona automágicamente! Gracias. Horas de la noche. Ya sabes cómo va :-) – Hooligancat

+0

Quise decir que observaste el error en mis formas, ¡no tu observación es el error! – Hooligancat

Cuestiones relacionadas