【发布时间】:2015-08-13 13:42:38
【问题描述】:
如何突出显示特定的NSMenuItem? NSMenu上只有方法highlightedItem,但没有setHighlightedItem
【问题讨论】:
标签: macos cocoa nsmenu nsmenuitem
如何突出显示特定的NSMenuItem? NSMenu上只有方法highlightedItem,但没有setHighlightedItem
【问题讨论】:
标签: macos cocoa nsmenu nsmenuitem
更新
通过浏览OS X Runtime headers,我在NSMenu 上发现了另一种不需要获取Carbon 菜单实现的方法。
该方法称为highlightItem:,并且可以按预期工作。
所以本质上,NSMenu 类别可以简化为以下内容:
@interface NSMenu (HighlightItemUsingPrivateAPIs)
- (void)_highlightItem:(NSMenuItem*)menuItem;
@end
@implementation NSMenu (HighlightItemUsingPrivateAPIs)
- (void)_highlightItem:(NSMenuItem*)menuItem
{
const SEL selHighlightItem = @selector(highlightItem:);
if ([self respondsToSelector:selHighlightItem]) {
[self performSelector:selHighlightItem withObject:menuItem];
}
}
@end
原始答案
虽然似乎没有正式的方法来执行此操作,但可以使用私有 (!) API。
这是我为NSMenu 写的一个类别,它允许您突出显示特定索引处的项目:
@interface NSMenu (HighlightItemUsingPrivateAPIs)
- (void)_highlightItemAtIndex:(NSInteger)index;
@end
@implementation NSMenu (HighlightItemUsingPrivateAPIs)
- (void)_highlightItemAtIndex:(NSInteger)index
{
const SEL selMenuImpl = @selector(_menuImpl);
if ([self respondsToSelector:selMenuImpl]) {
id menuImpl = [self performSelector:selMenuImpl];
const SEL selHighlightItemAtIndex = @selector(highlightItemAtIndex:);
if (menuImpl &&
[menuImpl respondsToSelector:selHighlightItemAtIndex]) {
NSMethodSignature* signature = [[menuImpl class] instanceMethodSignatureForSelector:selHighlightItemAtIndex];
NSInvocation* invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setTarget:menuImpl];
[invocation setSelector:selHighlightItemAtIndex];
[invocation setArgument:&index atIndex:2];
[invocation invoke];
}
}
}
@end
首先,它获取NSMenu 的Carbon 菜单实现(NSCarbonMenuImpl),然后使用指定的索引继续调用highlightItemAtIndex:。该类别的编写方式是,如果 Apple 决定更改此处使用的私有 API,它会优雅地失败。
【讨论】: