【问题标题】:Setting C function as selector for NSButton produces no results将 C 函数设置为 NSButton 的选择器不会产生任何结果
【发布时间】:2014-12-25 01:57:06
【问题描述】:

我有一个创建按钮实例的函数,我希望回调转到一个单独的函数。这不起作用(没有错误或任何事情,当我单击按钮时什么也没有发生)。我需要它是一个 C 函数,因为我正在与 Golang 交互(使用 cgo)。

void Start(void){
    ...
    NSRect buttonFrame = NSMakeRect(59, 33, 82, 32);
    NSButton *button = [[NSButton alloc] initWithFrame:buttonFrame];
    [button setAction:@selector(ButtonClick:)];
    ...
}
void ButtonClick(void){
    NSLog(@"Button clicked!");
}

【问题讨论】:

  • 只是一个想法:尝试在 sn-p 的第 5 行上方添加[button setTarget:self];
  • 未声明的标识符self。我在这里写的内容显示了一切,减去制作窗口等并运行它(在Start 内完成)。
  • 您不能为此使用函数。按钮必须有一个作为对象的目标,在该目标上可以使用具有适当名称的方法。
  • 这不是 C 文件;您正在发送消息(方括号语法),因此您必须编译为 ObjC。
  • 如果您需要在单击按钮时调用 C 函数,因为您想桥接到 Golang,您必须让按钮调用一个方法,然后该方法调用 C 函数。

标签: objective-c cocoa nsbutton target-action


【解决方案1】:

您不能将 C 函数用作 NSButton 的操作。该按钮需要target which is an object and the selector for a method on that target。如果没有目标,那么您窗口的responder chain 中一定还有一个对象会响应选择器。

您必须创建一个对象(不必是实例;如果您愿意,可以使用类对象)才能使按钮操作。该方法还需要有一个特定的签名:它必须有一个参数,即调用时的按钮。

如果您必须使用已经编写的函数,则必须编写一个 ObjC 类,该类从 action 方法调用它:

#import <Cocoa/Cocoa.h>

@interface ButtonPasser : NSObject

+ (IBAction)buttonPassthrough:(id)sender;

@end

@implementation ButtonPasser

+ (IBAction)buttonPassthrough:(id)sender
{
    buttonClick();
}

@end

void start(void){
    ...
    NSRect buttonFrame = NSMakeRect(59, 33, 82, 32);
    NSButton *button = [[NSButton alloc] initWithFrame:buttonFrame];
    [button setTarget:[ButtonPasser class]];
    [button setAction:@selector(buttonPassthrough:)];
    ...
}

这使用了类对象和类方法,因为我不确定在创建实例后你会如何处理它。但是,使用实例会更常见。

【讨论】:

  • 对象是实例,对吗?我从未听说过“类对象”。
  • 类是 ObjC 中的对象:stackoverflow.com/questions/6469770/…
  • 很好,@matt!我将用它来替换我的答案中断开的链接。谢谢!
  • 谢谢!作为后续(之后我会给你检查)一个简单的对象会是什么样子,以及将它设置为我的按钮的目标?
  • nil 的目标不是空操作。它针对响应者链。尽管最终将使用-performSelector:withObject: 之类的方式传递操作,但这并不是按钮立即发出的调用。该按钮将执行[NSApp sendAction:self.action to:self.target from:self],应用程序将搜索目标,如果它是nil
【解决方案2】:

您的问题是您的 Start 或 ButtonClick 方法(应该是 start 和 buttonClick)都不是实例方法。它们都必须绑定到一个对象才能将 buttonClick 设置为一个操作。

一旦这两种方法都是实例方法,您应该可以在 setAction 调用上方添加[button setTarget:self];

如果你不能启动一个实例方法,你应该在你的调用之间添加另一个方法。

【讨论】:

  • 正如我在提示中所说,对于我正在尝试做的事情,我需要一个 function(全局,类似于 void f(void){})来运行,不是某个对象的方法。
  • 这不是实现按钮的正确方法。按钮操作必须发送到对象的实例方法。
  • Cocoa 是一个 Objective-C 框架。它不适用于静态函数。如果要捕获对按钮的单击,则必须使用 Objective-C 方法。我真的不明白你为什么希望 Objective-C 框架像 C 库一样工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-07
  • 1970-01-01
  • 1970-01-01
  • 2017-03-18
  • 1970-01-01
  • 2021-08-15
相关资源
最近更新 更多