2010-10-01 4 views
9

Ich habe einige Probleme mit der Implementierung QuickLook Funktionalität aus einer Tabelle in einem NSView. Die begrenzte Dokumentation über QuickLook hilft wirklich überhaupt nicht.QuickLook Consumer als Stellvertreter von einem NSViewController

Nach dem Lesen durch die Apple Docs (die stark auf benutzerdefinierte Generatoren und Plugins ausgerichtet sind), endete ich mit Blick auf die . Dieser Code basiert auf einer dokumentenbasierten Anwendung, scheint aber die richtige Methode für mich zu sein (schließlich ist es Apples Code und funktioniert in ihrem Projekt).

In meiner Implementierung kann ich die QuickLook panel bekommen, um gut zu zeigen, und ich kann es genauso einfach ablehnen. Das Panel selbst ruft jedoch niemals die Delegate-Methoden aus meiner NSViewController. Als Ergebnis bekomme ich nie sogar Objekte zu zeigen, nur die Formulierung "Keine Artikel ausgewählt". Und ich bin ratlos.

Ich versuchte, ein setDelegate nennen, aber über drohendes Unheil gewarnt, wenn ich hinunter diesen Weg fortsetzen ...

[QL] QLError(): - [QLPreviewPanel setDelegate:] genannt, während die Platte nicht hat Controller - Fix dies oder das wird bald erhöhen. Siehe Kommentare in QLPreviewPanel.h für -acceptsPreviewPanelControl:/- beginPreviewPanelControl:/- endPreviewPanelControl :.

Und dann Doom passiert sowieso mit einem Dealloc beim Versuch, auf eine der Delegate-Methoden zu reagieren.

Und ja, ich habe die Kopfzeile gelesen, die bestätigt, dass ich den Delegierten einstellen sollte, nachdem ich das Panel gewonnen habe (siehe Code unten).

Also hier ist mein Code, der ziemlich genau dem Beispielcode mit Ausnahme von a) entspricht, woher ich meine Daten bekomme (ich bekomme es von einer NSArrayController) und die b) wo ich meine Vorschau Artikel von (mine kommt direkt von meinem Modellobjekt - oder sollte sowieso)

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

das Problem scheint zu sein, dass die acceptsPreviewPanelControl nie aufgerufen wird, so erhalten die Delegierten nie benutzt (sie definitiv nie) aufgerufen.

Ich bin sicher, dass dies ein einfacher Schritt ist, den ich vermisse, aber nachdem ich den Beispielcode seziert und die Dokumente durchforstet habe, sehe ich keine Antwort.

Ist es, weil dies alles innerhalb eines NSViewController ist (obwohl ich keinen Grund sehe, warum das überhaupt in die Gleichung kommen sollte)?

Alle und alle helfen sehr geschätzt.

LÖSUNG UPDATE

Dank Peters Beobachtung, war das Update eine schnelle ein. Hassen Sie es nicht, wenn die Fehlermeldung im Debugger bedeutet, was es sagt? :-)

In meiner Klasse, die geladen MyViewController Ich musste einfach drei Zeilen Code hinzufügen, um das Problem zu beheben.

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

Arbeit erledigt :-) Danke Peter.

Antwort

6

Warum würden Sie erwarten, dass es Ihnen Delegiertenmeldungen sendet, wenn Sie (noch) nicht Delegierter sind? Wenn Sie möchten, dass Ihnen Delegatnachrichten gesendet werden, müssen Sie sich als Delegat festlegen.

Ich versuchte, ein setDelegate nennen, aber über drohendes Unheil gewarnt, wenn ich hinunter diesen Weg fortsetzen ...

[QL] QLError(): -[QLPreviewPanel setDelegate:] genannt, während die Platte keine Steuerung hat - Fix diese oder das wird bald steigen. Siehe Kommentare in QLPreviewPanel.h für -acceptsPreviewPanelControl:/-beginPreviewPanelControl:/-endPreviewPanelControl:.

"Kein Controller", heißt es. Sie brauchen also einen Controller.

Die Kommentare zu diesem Header, insbesondere auf acceptsPreviewPanelControl: und die QLPreviewPanel Instanzmethode updateController, legen nahe, dass die Steuerung des Panels, wenn es eine, ein Objekt, das in der Antwortkette ist. Wenn Ihr Controller nicht zum Controller des Panels wird, liegt das daran, dass Ihr Controller nicht in der Responder-Kette ist.

Also, beheben Sie das, und dann wird es funktionieren.

Ich würde mir vorstellen, dass Ihr View-Controller in der Responder-Kette sein sollte, wenn seine Ansicht oder eine Unteransicht davon in der Responder-Kette ist, aber vielleicht ist dies nicht der Fall. The documentation sagt nicht. Wenn alles andere fehlschlägt, legen Sie sich explizit als nächster Beantworter einer Ansicht fest (und den vorherigen nächsten Beantworter als nächsten Beantworter), und senden Sie dann dem Vorschaubereich eine Nachricht updateController.

+0

Wie immer Peter Ihre Beobachtung war der Fehler in meinen Wegen. Ich hatte die Vorstellung übersehen, dass der NSViewController in die Responder-Kette hinzugefügt werden muss (im Gegensatz zu einem Fenster-Controller, der automatisch eingebunden wird). 3 Zeilen Code und das Problem ist automatisch behoben! Vielen Dank. Späte Nächte. Sie wissen, wie es geht :-) – Hooligancat

+0

Ich meinte, Sie beobachteten den Fehler in meinen Wegen, nicht Ihre Beobachtung ist der Fehler! – Hooligancat