NSPopupButton
的内容绑定到NSArray
个字符串。
我们如何通过绑定插入分隔符项?
" -
"字符串(如旧时/经典日)不起作用,即字面意思显示为" -
"菜单项。
是否有标准Cocoa类和绑定的开箱即用解决方案?
这应该是一个微不足道的问题,但我找不到任何解决问题的方法,这些问题并不涉及像子类NSMenu
,NSPopupButton
或其他非直观工作那样的愚蠢黑客攻击变通。
答案 0 :(得分:6)
在使用绑定时,我无法找到一种干净的方法来动态地将分隔符添加到菜单中。我发现的最简单(也是最可重用)的方法是使用NSMenuDelegate动态地将具有@"---"
的特定标题的NSMenuItem替换为menuNeedsUpdate:
委托方法中的分隔项。
第1步: 创建符合NSMenuDelegate协议的NSObject
#import <Cocoa/Cocoa.h>
@interface SeparatorMenuDelegate : NSObject <NSMenuDelegate>
@end
@implementation SeparatorMenuDelegate
-(void)menuNeedsUpdate:(NSMenu *)menu {
NSArray* fakeSeparators = [[menu itemArray] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"title == '---'"]];
for (NSMenuItem* fakeSep in fakeSeparators) {
[menu insertItem:[NSMenuItem separatorItem] atIndex:[menu indexOfItem:fakeSep]];
[menu removeItem:fakeSep];
}
}
@end
第2步:在Interface Builder中进行链接。
将Object拖出到包含NSPopupButton实例的场景中。
将对象的类设置为SeparatorMenuDelegate
旋转打开文档大纲中的NSPopupButton控件,然后选择其中的菜单。然后将菜单的委托设置为您之前拖动的SeparatorMenuDelegate
对象。
此后,菜单中的所有项目标题为@&#34; ---&#34;将被转换为分隔项。
如果在同一场景中有多个NSPopupButton实例,则可以将其Menu的委托设置为同一个对象(每个场景只需要一个SeparatorMenuDelegate
)。
答案 1 :(得分:4)
恕我直言,最干净的解决方案仍然是继承 NSMenu - 这种定制正是子类化的目的。以下解决方案基于@matt多年前在Cocoabuilder上所写的内容,并更新为更普遍适用,包括在High Sierra上。
首先,定义一个“魔术字符串”来表示代码中的分隔符项;在头文件中执行此操作,所有受影响的类将导入。在这个例子中,我选择了“---”,但当然,这可以是你喜欢的任何字符串:
#define MY_MENU_SEPARATOR @"---"
第二次,子类 NSMenu 并覆盖添加菜单项的两种方法,以便处理特殊的分隔符大小写:
@implementation MyMenu
- (NSMenuItem*)addItemWithTitle:(NSString*)aString action:(SEL)aSelector keyEquivalent:(NSString*)keyEquiv
{
if ([aString isEqualToString:MY_MENU_SEPARATOR])
{
NSMenuItem *separator = [NSMenuItem separatorItem];
[self addItem:separator];
return separator;
}
return [super addItemWithTitle:aString action:aSelector keyEquivalent:keyEquiv];
}
- (NSMenuItem*)insertItemWithTitle:(NSString*)aString action:(SEL)aSelector keyEquivalent:(NSString*)keyEquiv atIndex:(NSInteger)index
{
if ([aString isEqualToString:MY_MENU_SEPARATOR])
{
NSMenuItem *separator = [NSMenuItem separatorItem];
[self insertItem:separator atIndex:index];
return separator;
}
return [super insertItemWithTitle:aString action:aSelector keyEquivalent:keyEquiv atIndex:index];
}
@end
就是这样。将受影响的菜单设置为 Interface Builder 的 Identity 检查器中的 MyMenu 类,并在需要的位置插入分隔符项。适用于菜单栏菜单和弹出窗口。
答案 2 :(得分:1)
这是斯莱夫特在Swift 3.1中的回答:
class MySeparatorMenuDelegate : NSObject, NSMenuDelegate {
func menuNeedsUpdate(_ menu: NSMenu) {
for (ix,mi) in menu.items.enumerated() {
if mi.title == "---" {
menu.removeItem(at: ix)
menu.insertItem(NSMenuItem.separator(), at: ix)
}
}
}
}
答案 3 :(得分:0)
查看Mac OS X 10.5中添加的NSContentPlacementTagBindingOption
文档。在Interface Builder的Bindings检查器中,这可用于弹出菜单按钮等元素;转到“值选择”部分,查看“内容放置标记”的任何内容类别(内容,内容对象,内容值)。字段值应该是与某个菜单项的标签号匹配的数字。
绑定数组的内容将插入菜单中,而不是具有指定标记值的项目。在这种情况下,静态菜单将包含您的分隔符项和至少一个其他项,以指定数组值的位置。
答案 4 :(得分:-1)
[[popupButton menu] addItem:[NSMenuItem separatorItem]];