On Sep 1, 2015, at 7:12 PM, Quincey Morris <
email@hidden> wrote:
For actions, I think you have two choices. One is to put the action method in the app delegate. Since this is part of the application scene, you can link a menu item to its actions, using the storyboard in IB. Or, link your menu item to First Responder within its own scene. (That is to say, leave it with a nil target.) That allows a run time determination to be made whether anything that responds to the action is in the responder chain at the time the menu item is used.
Indeed, connecting to an outlet defined in appDelegate.swift worked perfectly. I'm not clear on the second option--the First Responder? I see it in the outline, but if the menu items have a nil target, how would I then use them to do anything?
The Cocoa app architecture maintains a concept called the responder chain. From any given responder there's a chain of other responders "up" through the app architecture, from views to view controllers to superviews and their controllers and eventually to the window, the window delegate, the app, and then then the app delegate.
There's also the notion of the first responder, which is the responder which has keyboard focus. It's in the key window.
Put those together and you get a responder chain from the first responder.
In a NIB or storyboard, there's a First Responder placeholder. If you attach any target-action connection to an action on that target, then the action is sent to the responder chain originating with the first responder. In reality, the First Responder placeholder doesn't actually represent any object. It represents the nil target. Any control or widget which delivers actions, when configured with a nil target, will deliver that action to the first responder and the chain up from there. See -[NSApplication sendAction:to:from:] for the specifics. Also see the Cocoa Event Handling Guide <
https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/EventOverview/Introduction/Introduction.html>.
Using appDelegate works, as I said, but it feels weird to split my UI code between that file and my view controller. I get why I have to, and I know that on OS X, it's more acceptable to put UI code in that file instead of a dedicated view controller, but the setup seems awkward. For instance, one of my menu items sets focus to an edit field, so the user can press the menu item's hotkey and start typing. The outlet for that field is, of course, in my view controller. With the menu item's action now in my appDelegate file, I'm stuck.
Does that menu item potentially switch which window is key and/or switch what view is showing within it? If not, if that menu item should only be active when the view is already in the responder chain from the first responder, then you can target the menu at the First Responder and handle it in your view controller. But that means the menu item will only be able to switch focus around within that view.
You could also put it in the window delegate if the menu item should only switch focus around within the key window. That will at least keep it somewhat closer to the point of interest.
I'll probably move all my actions and outlets to the appDelegate (assuming that works), leaving my view controller with little to do.
That probably won't work. As Quincey said, you won't be able to connect outlets across NIB/scenes, either. So, the app delegate can't have an outlet to a text field in your view.
As I said, this isn't a show-stopping problem, it's just odd to pull view controlling code *out* of my view controller and put it somewhere else.
Well, if the code needs to change which window is key, which views are present/active within that window, and then which control has focus, then it isn't really view-controlling code. It's much more global than that.
You may need to make the action method call into a one-level-deeper controller, which will then figure out where to go next. So, the action method for the menu item may target the app delegate. The app delegate would only know which window controller is associated with the action, not which view within it. So, it would call a method on that window controller. The window controller would know which view controller is appropriate, and call into that. (Or maybe there will be a hierarchy of view controllers.)
Regards,
Ken