2010-10-01 9 views
9

Sto riscontrando alcuni problemi nell'implementazione della funzionalità QuickLook da una tabella in un NSView. La documentazione limitata su QuickLook in realtà non aiuta affatto.Utente QuickLook come delegato da un NSViewController

Dopo aver letto il numero Apple Docs (che è fortemente orientato verso generatori e plug-in personalizzati), ho finito con lo QuickLookDownloader sample code. Questo codice si basa su un'applicazione basata su documenti, ma sembra essere il metodo giusto per me (dopotutto è il codice di Apple e funziona nel loro progetto).

Nella mia implementazione posso ottenere il QuickLook panel per presentarsi bene, e posso liquidarlo altrettanto facile. Tuttavia, il pannello stesso non chiama mai i metodi delegati dal mio NSViewController. Di conseguenza non riesco nemmeno a visualizzare oggetti, solo la dicitura "Nessun elemento selezionato". E sono perplesso.

Ho provato a chiamare un setDelegate, ma vengo avvertito imminente castigo se continuo questa strada ...

[QL] QLError(): - [QLPreviewPanel setDelegate:] chiamato mentre il pannello non ha controller - Risolvi questo o questo aumenterà presto. Vedere i commenti in QLPreviewPanel.h per -acceptsPreviewPanelControl:/- beginPreviewPanelControl:/- endPreviewPanelControl :.

E quindi il doom si verifica comunque con un dealloc quando si tenta di rispondere a uno dei metodi delegati.

E sì, ho letto l'intestazione che conferma che dovrei impostare il delegato dopo aver vinto il pannello (vedi codice sotto).

Quindi ecco il mio codice, che praticamente corrisponde al codice di esempio con l'eccezione di a) da cui ottengo i miei dati (l'ho preso da un NSArrayController) e il b) da cui ottengo il mio elemento di anteprima (il mio viene direttamente dal mio modello oggetto - o dovrebbe comunque)

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

il problema sembra essere che il acceptsPreviewPanelControl mai viene chiamato, in modo che i delegati non si abitua (che sicuramente non vengono chiamati).

Sono sicuro che questo è un passaggio semplice che mi manca, ma dopo aver analizzato il codice di esempio e aver setacciato i documenti, non vedo la risposta.

È perché questo è tutto all'interno di un NSViewController (anche se non vedo alcuna ragione per cui dovrebbe entrare nell'equazione)?

Qualsiasi e tutti gli aiuti molto apprezzati.

soluzione di aggiornamento

Grazie all'osservazione di Peter, la correzione è stata una veloce. Non lo odi quando il messaggio di errore nel debugger indica cosa dice? :-)

Nella mia classe che ha caricato MyViewController ho semplicemente dovuto aggiungere tre righe di codice per risolvere il 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]; 

Lavoro svolto :-) Grazie Peter.

risposta

6

Perché ti aspetteresti che ti invii messaggi delegati se non sei (ancora) un suo delegato? Se vuoi che ti invii dei messaggi delegati, devi impostarti come delegato.

Ho provato a chiamare un setDelegate, ma vengo avvertito imminente castigo se continuo questa strada ...

[QL] QLError(): -[QLPreviewPanel setDelegate:] chiamato mentre il pannello ha un controllore - Correggi o questo aumenterà presto. Vedere i commenti in QLPreviewPanel.h per -acceptsPreviewPanelControl:/-beginPreviewPanelControl:/-endPreviewPanelControl:.

"Nessun controller", si dice. Quindi, ne hai bisogno per avere un controller.

I commenti su tale intestazione, in particolare su acceptsPreviewPanelControl: e il metodo di istanza QLPreviewPanel updateController, suggeriscono che il controller del pannello, quando ne ha uno, è un oggetto che si trova nella catena di risposta. Pertanto, se il controller non sta diventando il controller del pannello, è perché il controller non si trova nella catena del risponditore.

Quindi, risolvilo, e poi funzionerà.

Immagino che il controller di visualizzazione debba essere nella catena di risposta ogni volta che la sua vista o qualsiasi sua sottoview si trova nella catena di risposta, ma forse questo non è il caso. The documentation non dice. Se tutto il resto fallisce, impostalo esplicitamente come risposta successiva di qualche vista (e il suo precedente risponditore successivo come rispondente successivo), quindi invia al pannello di anteprima un messaggio updateController.

+0

Come al solito Peter la tua osservazione è stata l'errore nei miei modi. Avevo trascurato il concetto che NSViewController ha bisogno di aggiungere nella catena di risposta (a differenza di un controller di finestra che viene automaticamente incluso). 3 righe di codice e il problema è risolto automagicamente! Grazie. Tarda notte. Sai come va :-) – Hooligancat

+0

Intendo che hai osservato l'errore nei miei modi, non la tua osservazione è l'errore! – Hooligancat

Problemi correlati