NSViewController in der Responder Chain

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • NSViewController in der Responder Chain

    Hi,
    ich habe eine Tabbar-App, bei der durch klicken auf die NSToolbarItem einer NSToolbar der entsprechende View in ein NSWindow (MainWindow) geladen wird. Da NSViewController von NSResponder erbt, dachte ich, dass es nicht so schwer sein kann, undo und redo actions an den entsprechenden NSViewController zu senden bzw. dem entsprechendem NSUndoManager.

    Zunächst verbinde ich MenuItems mit dem First Responder in meiner Nib-Datei, in der sich auch das MainWindow (Window mit Toolbar) befindet. Wenn ein ViewController geladen wird schreibe ich folgenden Code:

    Quellcode

    1. if ([window makeFirstResponder:viewController]) {
    2. NSLog(@"View controller is first responder");
    3. }


    und setze den View des ViewControllers als ContentView des MainWindows.

    Mein NSViewController hat eine Property (NSUndoManager *)undoManager und einen entsprechenden getter. Es werden, wenn ich Änderungen an den Inhalten durchführe, auch Undo-Actions registriert, der NSViewController ist First Responder und trotzdem sind die MenuItem nicht enabled. Ich kann die Enabled-Eigenschaft auch nicht an den First Reponder binden (ist ja logisch ;) ).

    Was fehlt noch damit das ganze funktioniert? Ich werde langsam raschelig und lese mir schon den ganzen Tag Tutorials, Dokus, etc. durch, die mich nicht weiter bringen, weil ich offensichtlich noch etwas falsch mache.

    Vielen Dank für eure Hilfe.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von jopjip ()

  • Soweit ich weiß, hängt ein View-Controller nicht in der automatischen Responder-Chain. Auch der Window-Controller ist ja nur deshalb drin, weil ein Fenster von der Klasse NSWindow ist und daher ein delegate hat, welches das Fenster kennt. /Dieses/, nicht der Responder-Dispatch, fragt seinen Controller, ob er was damit anfangen kann. Also musst du das bei deinem View ebenso machen. Wie das im einzelnen geht, ist irgendwo dokumentiert. Man muss eine Methode überschreiben (-respondsToSelector:?), damit beim Enabling erkannt wird, dass da ein weiterer ist, der Action_Messages verbrauchen kann.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Ich habe noch ein Problem gefunden: Wenn ich in View A undo actions auslöse bzw. registriere werden die MenuItems enabled. Wechsel ich den ContentView im Window dann werden die MenuItems disabled (soweit ja richtig, da für diesen Bereich noch keine undo-actions registiert sind), wechsel ich zurück zu View A bleiben die entsprechenden MenuItems disabled. Löse registriere ich daraufhin eine neue undo-action werden die MenuItems wieder enabled und die undo-actions, die ich ganz zu anfang registriert habe sind auch verfügbar.

    Folgendes habe ich schon ausprobiert:

    • Die Action, die dafür sorgt, dass der ContentView gewechselt wird, wird an den First Responder gesendet (anstatt direkt an den AppDelegate [Subklasse von NSResponder])
    • [[NSApplication sharedApplication].mainMenu update] oder [window.menu update]; sobald der ContentView gewechselt wird.
    • die -update method direkt an das Outlet des MainMenu geschickt, wenn der ContentView geändert wird.


    Außerdem habe ich das MainMenu auf [mainMenu setAutoenablesItems:YES]; gesetzt.

    Bisher hat noch nichts funktioniert.

    Was habe ich diesmal nicht beachtet/vergessen?
  • Quellcode

    1. // im Viewcontroller
    2. - (void)insertIntoResponderChain
    3. {
    4. NSResponder *nextResponder = [ self.view nextResponder ];
    5. [ self.view setNextResponder:self ];
    6. [ self setNextResponder:nextResponder ];
    7. }

    Irgendwie scheint mir das mit dem NSViewController unter Mac OS von Apple aber nicht zu Ende gedacht. Du bekommst keine Benachrichtigungen (-viewDidLoad, -viewRemoved etc.) und um die responderchain musst Du Dich auch zu Fuss kümmern.
  • Okay, ich verbessere mich:

    Einfach -supplementalTargetForAction:sender: richtig implementieren. Sollte funktionieren und dauert mutmaßlich 5 Stunden.

    :-]

    Wie ich bereits sagte: Das View ist in der Responder-Chain, nicht der View-Controller. Deshalb muss das View den View-Controller berücksichtigen. Also musst du diese Methode im View implementieren und den View-Controller zurückliefern.

    Ansonsten kann ich nur erneut die Lektüre der DOkumentation zu Responder-Chains wärmstens an Herz legen.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?