Jonas Felber
Jonas Felber

Reputation: 429

Handle Menu Item Action in ViewController

I want to handle a click tot the menu item 'Open' in my view controller.

It seems to be only possible to handle it in my AppDelegate. The problem described here [1] is very similar on what I want to do, but I think there must be a way that is more dynamic and does not require the AppDelegate to know where to forward it exactly. What if I want to change the action depending on the current view?

This is my first application that I code with cocoa, so I am not yet very familiar with 'Responder Chains'[2] and 'Delegation', but it seems like I have to do something with those.

[1] Connect to ViewController from AppDelegate (Swift)
[2] Cocoa Storyboard Responder Chain

Upvotes: 4

Views: 3478

Answers (1)

Caleb
Caleb

Reputation: 124997

What if I want to change the action depending on the current view?

You really do need to understand the responder chain in order to get how menu commands are handled. Briefly, views, view controllers, window controllers, documents, and the application itself are all instances of NSResponder, which provides the mechanism for handling events like key presses and menu commands. At any given moment there's a "first responder," which is the first object that will get a shot at handling these kinds of events. If that object doesn't handle the event in question, the event gets passed up to the next responder in the chain, and so on, until it gets to the application.

For example, when you type the letter "a" in a Cocoa-based text editor, that key press is sent to the first responder. If there's a document window open and active, then the first responder is probably going to be some text view, which will insert the "a" at the insertion point and perhaps notify its delegate that the text changed. If you choose the File->Close command with that same window active, on the other hand, that event will start at the text view, which might not handle it, so it'll be passed up to the superview, to the window, to the window controller, and finally arrive at the document, which knows how to handle that command. If the command were File->Quit, on the other hand, the command would go all the way up to the application before it got handled. This is known as the "responder chain" in Cocoa and Cocoa Touch programming, but the pattern here is also known as "chain of responsibility." The responder chain is used not only for handling events, but also for things like menu validation.

Context menu commands are handled the same way. The only thing that's really different is how the context menu is created: when the user performs whatever gesture brings up a context menu (control-click or right click, usually) the context menu is built on the fly by asking the first responder (again, the thing that's currently "in focus") what menu should be shown. NSView has a -menuForEvent: method that normally just returns the contents of the view's menu property, so you can either set up the menu property with an instance of NSMenu, or you can override -menuForEvent: so that it builds the menu. When the user chooses a context menu command, it'll be processed like any other menu command, starting with the first responder. That means that the first responder doesn't necessarily need to handle all the items in the context menu it provides -- there might be items like "Copy" or "Paste" that are handled by other objects further up the chain.

Upvotes: 6

Related Questions