Cocoa Storyboard Responder-Kette

8

Storyboards für Cocoa-Apps scheinen eine großartige Lösung zu sein, da ich die Methodik von iOS bevorzuge. Wenngleich das Aufteilen in separate View-Controller sehr logisch ist, ist mir nicht klar, wie die Fenstersteuerung (Symbolleistenschaltflächen) oder die Menüinteraktion an die betrachteten View-Controller übergeben werden sollen. Mein App-Delegat ist der Ersthelfer und empfängt die Menü- oder Symbolleistenaktionen. Wie kann ich jedoch auf den Ansichtscontroller zugreifen, auf den ich diese Nachricht erhalten soll? Können Sie nur einen Blick in die View-Controller-Hierarchie werfen? Wenn ja, wie kommen Sie vom App-Delegierten dorthin, da es der Ersthelfer ist? Können Sie stattdessen den Fenstercontroller zum Ersthelfer machen? Wenn das so ist, wie? Im Storyboard? Wo?

Da dies eine Frage auf hoher Ebene ist, spielt es keine Rolle, aber ich verwende Swift für dieses Projekt, wenn Sie sich fragen.

    
Matt Long 04.11.2014, 20:57
quelle

5 Antworten

5

Ich bin nicht sicher, ob es eine " richtige " Möglichkeit gibt, dies zu lösen, aber ich habe mir eine Lösung ausgedacht, die ich für jetzt verwenden werde. Zuerst ein paar Details

  • Meine App ist eine dokumentbasierte Anwendung, so dass jedes Fenster eine Instanz des Dokuments enthält.

  • Das Dokument, das die App verwendet, kann als Ersthelfer fungieren und alle Aktionen weiterleiten, an die ich mich angeschlossen habe

  • Das Dokument kann den Fenstercontroller der obersten Ebene erfassen und von dort aus kann ich durch die View-Controller-Hierarchie navigieren, um zum benötigten View-Controller zu gelangen.

Also, in meinem windowDidLoad auf dem Fenster-Controller, mache ich das:

%Vor%

Was mir den View-Controller bringt (der die Ansicht steuert, die unten rot markiert ist) und legt eine lokale Eigenschaft im Fenster-View-Controller fest.

Nun kann ich die Symbolleistenschaltfläche oder die Menüelementereignisse direkt in der Dokumentklasse weiterleiten, die sich in der Antwortkette befindet, und erhält daher die Aktionen, die ich in den Menü- und Symbolleistenelementen eingerichtet habe. So:

%Vor%

Da der LayerCanvasViewController beim Laden als eine Eigenschaft des Hauptfenster-Controllers eingestellt wurde, kann ich einfach darauf zugreifen und die Methoden aufrufen, die ich brauche.

    
Matt Long 06.11.2014 18:34
quelle
2

Um die View-Controller zu finden, müssen Sie -supplementalTargetForAction: sender: in Ihrem Fenster und View-Controller implementieren.

Sie können alle möglicherweise an der Aktion interessierten untergeordneten Controller auflisten oder eine generische Implementierung verwenden:

%Vor%     
Pierre Bernard 13.12.2014 10:37
quelle
1

Ich hatte das gleiche Storyboard-Problem, aber mit einer einzigen Fenster-App ohne Dokumente. Es ist ein Port einer iOS App und meine erste OS X App. Hier ist meine Lösung.

Fügen Sie zuerst eine IBAction wie oben in Ihrem LayerDocument hinzu. Gehe nun zum Interface Builder. Sie werden sehen, dass IB im Verbindungsbereich zu First Responder in Ihrem WindowController jetzt eine gesendete Aktion von addLayer hinzugefügt hat. Verbinden Sie Ihr ToolBarItem damit. (Wenn Sie sich First-Responder-Verbindungen für einen anderen Controller ansehen, wird es eine Received Action von addLayer haben. Ich konnte damit nichts anfangen. Was auch immer.)

Zurück zu windowDidLoad. Fügen Sie die folgenden zwei Zeilen hinzu.

%Vor%

Das sollte es tun. Jetzt, wenn Sie auf die Symbolleiste klicken, wird es direkt zu Ihrer Aktion gehen.

    
Paul Linsay 12.12.2014 16:27
quelle
1

Ich habe selbst mit dieser Frage gekämpft.

Ich denke, die "richtige" Antwort besteht darin, sich auf die Responder-Kette zu stützen. Um beispielsweise eine Aktion für eine Werkzeugleiste zu verbinden, können Sie den ersten Beantworter des Root-Fenster-Controllers auswählen. Und dann den Attributinspektor anzeigen. Fügen Sie im Attributinspektor Ihre benutzerdefinierte Aktion hinzu (siehe Foto).

Verbinden Sie dann Ihren Toolbar-Eintrag mit dieser Aktion. (Ziehen Sie den Mauszeiger von Ihrem Toolbar-Element zum ersten Responder und wählen Sie die Aktion aus, die Sie gerade hinzugefügt haben.)

Schließlich können Sie dann zum ViewController (+ 10.10) oder einem anderen Objekt gehen, solange es in der Responder-Kette ist, wo Sie dieses Ereignis erhalten und den Handler hinzufügen möchten.

Alternativ dazu, anstatt die Aktion im Attribute-Inspector zu definieren. Sie können Ihre IBAction einfach in Ihren ViewController schreiben. Gehen Sie dann zu dem Toolbar-Element und steuern Sie den Drag-Befehl zum ersten Responder des Fenster-Controllers - und wählen Sie die gerade hinzugefügte IBAction aus. Das Ereignis wird dann durch die Responder-Kette reisen, bis es vom View-Controller empfangen wird.

Ich denke, das ist der richtige Weg, dies zu tun, ohne eine zusätzliche Kopplung zwischen Ihren Controllern einzuführen und / oder den Anruf manuell weiterzuleiten.

Die einzige Herausforderung, auf die ich gestoßen bin - ich bin neu bei Mac dev - ist manchmal, dass das Toolbar-Element sich selbst deaktiviert hat, nachdem es das erste Ereignis erhalten hat. Also, während ich denke, dass dies der richtige Ansatz ist, gibt es immer noch einige Probleme, die ich selbst erlebt habe.

Aber ich kann das Ereignis an einem anderen Ort ohne zusätzliche Kopplung oder Gymnastik erhalten.

    
Bladebunny 25.02.2015 23:35
quelle
0

Da ich eine sehr faule Person bin, habe ich die folgende Lösung basierend auf Pierre Bernard gefunden 's Version

%Vor%

Auf diese Weise müssen Sie den Forwarder-Code nicht zum Fenster-Controller und allen Viewcontrollern hinzufügen (obwohl Unterklassen das ein bisschen einfacher machen würden), die Magie passiert automatisch, wenn Sie einen View-Controller für das Fenster contentview haben.

>

Swizzling ist immer ein bisschen gefährlich, also ist es bei weitem keine perfekte Lösung, aber ich habe es mit einer sehr komplexen View / Viewcontroller-Hierarchie versucht, die mit Container-Ansichten funktionierte.

    
Hofi 09.02.2018 23:58
quelle