禁止自动处理NSButton单选按钮组



我正在开发一个在macOS和Windows中运行的跨平台动态对话框生成器。我继承了这个代码库。我正在努力支持单选按钮。问题是,如果所有单选按钮共享相同的超级视图和相同的操作选择器,macOS会自动将它们视为一个组。此代码对所有按钮使用一个操作选择器,对所有控件只有一个超级视图。因此,一组单选按钮就像魔术一样,但不可能在窗口上有多个组。

我正在寻求如何处理这一问题的建议。

  • 有没有办法抑制NSButtonStyleRadio的自动行为
  • 有没有一种方法可以动态创建指向同一代码的选择器?(见下文。(

一个棘手的解决方案可能是内置一些单选按钮选择器方法,然后在一个窗口上不允许超过那么多组。它看起来像这样:


- (IBAction)buttonPressed:(id)sender // this is the universal NSButton action
{
if (!_pOwner) return; // _pOwner is a member variable pointing to a C++ class that handles most of the work
int tagid = (int) [sender tag];
_pOwner->Notify_ButtonPressed(tagid);
}
- (IBAction)radioButtonGroup1Pressed:(id)sender
{
if (_pOwner)
[(id)_pOwner->_GetInstance() buttonPressed:sender];
}
- (IBAction)radioButtonGroup2Pressed:(id)sender
{
if (_pOwner)
[(id)_pOwner->_GetInstance() buttonPressed:sender];
}
- (IBAction)radioButtonGroup3Pressed:(id)sender
{
if (_pOwner)
[(id)_pOwner->_GetInstance() buttonPressed:sender];
}
- (IBAction)radioButtonGroup4Pressed:(id)sender
{
if (_pOwner)
[(id)_pOwner->_GetInstance() buttonPressed:sender];
}

这个例子将允许在窗口上最多有4个按钮组,我可以跟踪我使用了哪些按钮组。但我真的很想避免用这种方式对它进行硬编码。有什么方法可以动态地做到这一点吗?或者同样可以,完全禁用自动行为?

简而言之,问题是在编译时无法知道NSWindowController类需要多少方法用于单选按钮组。因此,解决方案是根据需要在运行时添加新方法。

我的代码有一个窗口控制器,部分声明如下。

@interface MyWindowController : NSWindowController
- (IBAction)buttonPressed:(id)sender; // universal button action for all button controls
.
.
.
@end

当程序创建窗口时,它会为窗口指定一个新的窗口控制器,然后在窗口上创建所有控件。对于每个控件,它会根据情况分配一个操作和/或一个通知监视器。对于单选按钮组,不直接将按钮分配给buttonPressed:,而是可以通过根据需要创建的按钮组特定方法进行路由。

// groupId: the integer id of the group on the window. (Mine counts from 1, but it doesn't matter.)
// button: the NSButton control being created.
SEL mySelector = NSSelectorFromString([NSString stringWithFormat:@"radioButtonGroup%dPressed:", groupId]);
class_addMethod([MyWindowController class], mySelector, (IMP)_radioButtonGroupPressed, "v@:@");
[button setAction:mySelector];

如果Objective-C++允许将lambda强制转换为(IMP),我会使用lambda作为方法,但我使用了这个静态函数。

// If class_addMethod allowed lambdas, this would be a lambda in the call to class_Method below.
static void _radioButtonGroupPressed(id self, SEL, id sender)
{
[self buttonPressed:sender];
}

NSSelectorFromString允许创建任意选择器名称,class_addMethod允许将其附加到代码中。如果已经添加了选择器,则class_addMethod不执行任何操作。

最新更新