Accessing IBOutlet from other classes

2019-02-26 09:56发布

问题:

I have a document based cocoa application with an item in the application menu hooked up to an IBAction. Clicking the item needs to perform a task that uses an IBOutlet in the main nib file which is using another class, MyDocument. Creating 2 objects of the same class, one in each nib seems to not be working. How can I access the outlet?

回答1:

Actions for menu items are often sent to the first responder so that whatever is currently selected can act on it.

It sounds like this action is something that works on the current document, then it should be implemented by the document. In this case have the menu send it's action to the first responder and then put the action method in the MyDocument class.

If the action you are trying to send is a custom one: in the Main Menu nib select the First Responder item, add your method name, then connect the menu item's selector to the action.

Read the Responders section of the Cocoa Event-Handling Guide for more info.



回答2:

To summarize the above, in your NIB/XIB file, in interface builder make the connection to the First Responder object, not to Files Owner or anything else. You'll still be offered a lit of actions across potential first responders.

Cocoa then takes that selector and looks for it, starting with the NSView (if any) that's currently the first responder, then with the NSDocument that's currently in use, then with it's window controller etc etc all the way up to the Application delegate. The first object it checks that actually implements that method, it will use that object (after validating it with that same object).

So:

@interface MyDocumentTypeA : NSDocument {
}

-(void)myMenuAction:(id)sender;

-

@interface MyDocumntTypeB : NSDocument {
}

// -myMenuAction: not implemented here

-

@interface MyApplicationDelegate ... {
}

-(void)myMenuAction:(id)sender;

-

In Interface builder (or even programmatically), if you've linked the "action" of the menu item to a selector named "myMenuAction:" on the First Responder (which equates to not specifying a target when done programmatically), for the above two document subclasses the following will happen.

For MyDocumentTypeA, when the user selects that menu item, MyDocumentTypeA's -myMenuAction: will be invoked. Since MyDocumentTypeB does not implement this action, Cocoa will continue to look up the responder chain until it gets to your application delegate, which does implement it, so it will be invoked here instead.

If Cocoa finds no objects in the responder chain that implement the method, the menu item remains disabled.



回答3:

There is a way how to do this, I've posted the answer in a similar thread: Access IBOutlet from other class (ObjC)