How to connect a menu item to a custom action defined in the NSApplication delegate across nib files?
In my Cocoa app I have two NIB/XIB files that I need to connect:
MainMenu.xib: contains a custom object for the NSApplication delegate object and connects it to the proper outlet in the
NSApplication
placeholder.ContextMenu.xib:开发者_Python百科 sets up an
NSMenu
; one entry is supposed to open the preferences dialog
My custom app delegate defines an IBAction
to bring up the Preferences window for my app.
How can I connect the NSMenuItem (second NIB) for showing the preferences to the action defined in the application delegate (first NIB)?
The Docs say this is supposed to be easy, but they fail to mention how exactly to do this in Interface Builder:
If the menu item refers to an application-level command, you can implement that command directly in the application delegate or just have the delegate forward the message to the appropriate object elsewhere in your application.
I somehow need to access the app delegate in the second NIB, tell Interface Builder that it is of my custom class (so it knows about the custom IBAction), and connect it to the action of the menu item.
Thanks for any pointers!
If the other objects are in the responder chain, then you can just hook the action up to the first responder.
Notice the "if", though.
As Maurice Kelly mentions, your App Delegate is already part of the responder chain, so you can use that: Define a custom action on the First Responder (in Interface Builder) and a corresponding action on your App Delegate. If you have many actions that could clutter up the App Delegate, though, so you might want to use this architecture only for simple apps.
For bindings in the second NIB, application delegate bindings can be accessed by binding to Application
with a model key path starting with delegate
. ie delegate.managedObjectContext
A warning: Do not create an app delegate object in the second NIB. If you do, you will end up with a second app delegate instance with a second, separate managedObjectContext. The NIB creates another app delegate object. This is terrible.
In the loading of MainMenu.xib, [NSApplication sharedApplication]
gets its delegate set to the delegate object instantiated in MainMenu.xib. If you create a delegate object in another NIB, you will have a delegate object that doesn't match [NSApp delegate]
. (And you will smash your head into the wall trying to discover why the view of the context doesn't update)
Your second NIB will have a File's Owner which you should set to a class that is instantiated by your application. Within this class you can create a reference to the App Delegate which can be filled in when the class is being instantiated (e.g. using setAppDelegate:self
if you are creating it from within the delegate).
Create an IBAction in this class which simply passes the action on to the App Delegate:
- (IBAction) passItOnAction:(id)sender {
[appDelegate openPreferences:sender];
}
I got the same problem, and solved it like this:
I created only one menu (MainMenu.xib). Since menu items for which the first responder does not provide any action are automatically greyed out, the items that are meant for the Document window will be greyed out when the Prefs window is activated.
I created a PrefsWin.xib for the definition of the prefs window. The File's Owner of that xib is a class named PrefsWinController, which inherits from NSWindowController.
The actions in MainMenu.xib simply connect to the First Responder rather than the delegate. If your instance of <NSApplicationDelegate> is an instance of NSResponder, the delegate will automatically act as the last responder in the chain. (I don't know where this might be documented, but it certainly works in my project.)
精彩评论