发送一个动作Cocoa - IBAction

7

我希望使用cocoa将一个动作发送到另一个对象。最理想的情况是,它也可以在Interface Builder中显示。

我已经尝试过苹果的文档,但似乎还缺少一些东西。添加以下内容后,接口构建器仅显示该操作为接收到的操作。

- (IBAction)setTarget:(id)anObject;
- (IBAction)setAction:(SEL)aSelector;

请问有没有人能给我举个创建发送操作的例子?谢谢。


我已经在我的控制器1中定义了接收操作。然后我希望我的控制器2能够发送一个操作到控制器1(就像NSButton做的那样)。在界面构建中,您可以从NSButton拖动一条线到应该接收信号的控件上。这个功能不能仅限于苹果对象,肯定有办法实现。

5个回答

18

IBAction 是一个预处理指令,它告诉Interface Builder“这是你应该知道的东西。” 它实际上评估为 void。这意味着“操作”只是普通方法,可以像平常一样调用:

[target someMethod:self];

如果您想模仿从NSButton获取的行为,可以添加一个用于目标的outlet和一个选择器属性(作为字符串):

@property (nonatomic, retain) IBOutlet id target;
@property (nonatomic, retain) NSString* actionSelectorString;

然后您可以这样调用:

SEL action = NSSelectorFromString(self.actionSelectorString);
[self.target performSelector:action withObject:self];
如果你想让你的类通过拖放在Interface Builder中连接选择器,最简单的方法是将你的类作为NSControl的子类(从对象库中拖动自定义视图,按Command-6显示检查器,在顶部弹出菜单中选择你的类)。然后可以通过以下方式“调用”操作:
- (void) go {
    [self sendAction:self.action to:self.target];
}

1
接口构建者是终极波特姆金村庄。或许更像... 一个斯特佛夫人。她非常努力,不让你看到里面发生了什么……然后你记起她其实是一个被烧毁的小镇,充满着可怕的、猴子补丁式的C汇编等等。 - Alex Gray
3
听起来你从未使用过其他的拖拽式界面构建工具,这些工具往往隐藏了更多的废物并生成了大量你不应该触碰的代码。IB 使用 ObjC 的动态运行时来完成有用但并非神奇的任务;它所做的一半已经在上面解释过了(另一半是设置属性),而且时间也不会太长,对吧? - TALlama
1
我有些傻了...你是对的...即使是Xcode生成的汇编也非常易读和优雅。(“产品”->“生成输出”->“汇编文件”)。然而,苹果在否认/假装无知存在任何过时或不端技术方面有一条有趣/尴尬的线路 - 至少在外部如此。他们只轻微地记录他们不想让你知道的运行时功能等。这都是合理和无害的...但这使得一些有趣的细节难以讨论和学习,特别是因为其中一些是故意禁止的水果。 - Alex Gray
@alexgray 你会读汇编吗?:O @TALlama 你的回答中有个错别字:@property ... NSString ... 应该是 @property ... NSString * ...(你忘了星号)。但是这个回答非常有帮助! - 11684

1

controller1和controller2是NSControl的子类。

[controller2 sendAction:@selector(receiveAction:) to:controller1];

1

动作总是由对象接收。如果您想向另一个方向发送信息,则可能需要一个出口:请寻找IBOutlet。


按钮(例如NSSegmentedcontrol)如何发送toggle:? - user75832
NSSegmentedControl只能向接受该消息的对象发送“toggle:”。aroneous是正确的:动作由接收者声明,而不是由发送者声明。 - Kristopher Johnson
是的,我已经在我的Controller1中定义了receive操作。然后,我希望我的Controller2能够向Controller1发送一个动作(就像NSButton一样)。在接口构建中,您可以将线从NSButton拖到应接收信号的控件上。这种功能不仅限于苹果对象,肯定有方法可以实现。 - user75832

1

NSButton是一个NSControl,因此具有可以连接的“操作”--当您触发控件时发送的消息(例如,单击按钮)。控制器没有操作(这意味着什么--您如何导致消息被发送?),因此您正在尝试做的事情实际上没有意义。

如果您希望controller2能够让controller1执行某些操作,则应在controller2上创建一个插座(类型为controller1或其实现的某个接口),将其连接到IB中的controller1,然后您可以从controller2向controller1编程发送任何消息。


1
如果你的Controller2类是NSControl的子类,那么你应该能够做到这一点。 NSControl定义了一个“发送操作”,这就是当你从Interface Builder中的NSButton拖动到目标对象时连接到它的内容。话虽如此,IB 3.0中存在(或曾经存在)一个bug,阻止了发送操作在IB中的显示。有关详细信息,请参见this cocoa-dev thread

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接