ForgetSou | Blog

❤ 武统台湾 刻不容缓 ❤

0%

macOS-NSMenu

macOS-NSMenu

1 简述

管理应用菜单的对象,通常会在程序的主菜单栏,视图右键菜单,Dock菜单使用。

@interface NSMenu : NSObject <NSCopying, NSCoding, NSUserInterfaceItemIdentification, NSAccessibilityElement, NSAccessibility>

2 NSMenu源码注解

2.1 创建

- (instancetype)initWithTitle:(NSString *)title NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;

2.2 常用属性

// 菜单标题
@property (copy) NSString *title;
// 父菜单
@property (nullable, assign) NSMenu *supermenu;
// 当前菜单下的子菜单数组
@property (copy) NSArray<NSMenuItem *> *itemArray;
// item数量
@property (readonly) NSInteger numberOfItems;
// 是否自动启用项目
@property BOOL autoenablesItems;
// 菜单高度
@property (readonly) CGFloat menuBarHeight;
// 高亮的item
@property (nullable, readonly, strong) NSMenuItem *highlightedItem API_AVAILABLE(macos(10.5));
// 最小宽度
@property CGFloat minimumWidth API_AVAILABLE(macos(10.6));
@property (readonly) NSSize size API_AVAILABLE(macos(10.6));
// 确定上下文菜单插件是否可以附加到菜单(如果用作上下文菜单)。
@property (null_resettable, strong) NSFont *font API_AVAILABLE(macos(10.6));
// 确定菜单是否包含状态图像的列
@property BOOL showsStateColumn API_AVAILABLE(macos(10.5));

2.3 常用函数

// 菜单栏是否可见,visible = NO 隐藏
+ (void)setMenuBarVisible:(BOOL)visible;
+ (BOOL)menuBarVisible;

// 添加和删除菜单项
- (void)insertItem:(NSMenuItem *)newItem atIndex:(NSInteger)index;
- (NSMenuItem *)insertItemWithTitle:(NSString *)string action:(nullable SEL)selector keyEquivalent:(NSString *)charCode atIndex:(NSInteger)index;
- (void)addItem:(NSMenuItem *)newItem;
- (NSMenuItem *)addItemWithTitle:(NSString *)string action:(nullable SEL)selector keyEquivalent:(NSString *)charCode;
- (void)removeItemAtIndex:(NSInteger)index;
- (void)removeItem:(NSMenuItem *)item;
- (void)removeAllItems API_AVAILABLE(macos(10.6));
- (void)itemChanged:(NSMenuItem *)item; // 在视觉上修改菜单项(例如,其标题更改)时调用。

// 查找菜单项
- (nullable NSMenuItem *)itemAtIndex:(NSInteger)index;
- (nullable NSMenuItem *)itemWithTitle:(NSString *)title;
- (nullable NSMenuItem *)itemWithTag:(NSInteger)tag;

// 查找菜单项的索引
- (NSInteger)indexOfItem:(NSMenuItem *)item;
- (NSInteger)indexOfItemWithTitle:(NSString *)title;
- (NSInteger)indexOfItemWithTag:(NSInteger)tag;
- (NSInteger)indexOfItemWithRepresentedObject:(nullable id)object; // 返回具有给定表示对象的菜单中第一个菜单项的索引。
- (NSInteger)indexOfItemWithSubmenu:(nullable NSMenu *)submenu; // 使用给定的子菜单返回菜单中菜单项的索引。
- (NSInteger)indexOfItemWithTarget:(nullable id)target andAction:(nullable SEL)actionSelector; // 返回菜单中具有指定操作和目标的第一个菜单项的索引。

3 NSMenuItem源码注解

@interface NSMenuItem : NSObject <NSCopying, NSCoding, NSValidatedUserInterfaceItem, NSUserInterfaceItemIdentification, NSAccessibilityElement, NSAccessibility>

// 初始化创建
- (instancetype)initWithTitle:(NSString *)string action:(nullable SEL)selector keyEquivalent:(NSString *)charCode NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;

// 启动项
@property (getter=isEnabled) BOOL enabled;

// 隐藏状态
@property (getter=isHidden) BOOL hidden API_AVAILABLE(macos(10.5)); // 菜单项是否隐藏
@property (getter=isHiddenOrHasHiddenAncestor, readonly) BOOL hiddenOrHasHiddenAncestor API_AVAILABLE(macos(10.5));

// Action & Target
@property (nullable, weak) id target;
@property (nullable) SEL action;

// 标题
@property (copy) NSString *title;
@property (nullable, copy) NSAttributedString *attributedTitle;

// 标签
@property NSInteger tag;

// 状态
@property NSControlStateValue state;
static const NSControlStateValue NSControlStateValueMixed = -1;
static const NSControlStateValue NSControlStateValueOff = 0;
static const NSControlStateValue NSControlStateValueOn = 1;

// 图片
@property (nullable, strong) NSImage *image;
@property (null_resettable, strong) NSImage *onStateImage; // checkmark by default
@property (nullable, strong) NSImage *offStateImage; // none by default
@property (null_resettable, strong) NSImage *mixedStateImage; // horizontal line by default

// 子菜单
@property (readonly) BOOL hasSubmenu;
@property (nullable, strong) NSMenu *submenu;
@property (nullable, readonly, assign) NSMenuItem *parentItem API_AVAILABLE(macos(10.6));

// 按键
@property (copy) NSString *keyEquivalent;
@property NSEventModifierFlags keyEquivalentModifierMask;

// 其它
@property (readonly, copy) NSString *userKeyEquivalent;
@property BOOL allowsKeyEquivalentWhenHidden API_AVAILABLE(macos(10.13));
@property (nullable, copy) NSString *toolTip;
@property (getter=isHighlighted, readonly) BOOL highlighted API_AVAILABLE(macos(10.5)); // 是否应突出显示菜单项
@property (nullable, strong) NSView *view API_AVAILABLE(macos(10.5)); // 菜单项的内容视图

4 实际应用

  • Main Menu

    使用StoryBoard添加Menu比较方便添加和删除

    Main Menu

  • 右键Menu

    NSView上添加Menu

    - (void)viewDidLoad {
    [super viewDidLoad];
    NSMenu *menu = [[NSMenu alloc] initWithTitle:@"view menu"];
    NSMenuItem *item1 = [[NSMenuItem alloc] initWithTitle:@"item 1" action:@selector(menuClick) keyEquivalent:@""];
    item1.target = self;
    NSMenuItem *item2 = [[NSMenuItem alloc] initWithTitle:@"item 2" action:@selector(menuClick) keyEquivalent:@""];
    item2.target = self;

    [menu addItem:item1];
    [menu addItem:item2];

    // 添加二级菜单
    NSMenu *menu2 = [[NSMenu alloc] initWithTitle:@"sub menu"];
    NSMenuItem *itemA = [[NSMenuItem alloc] initWithTitle:@"itemA" action:@selector(menuClick) keyEquivalent:@""];
    itemA.target = self;
    NSMenuItem *itemB = [[NSMenuItem alloc] initWithTitle:@"itemB" action:@selector(menuClick) keyEquivalent:@""];
    itemB.target = self;
    [menu2 addItem:itemA];
    [menu2 addItem:itemB];
    // 二级菜单放在指定item上
    [menu setSubmenu:menu2 forItem:item2];
    self.view.menu = menu;

    }

    - (void)menuClick {

    }
  • Dock菜单

    在AppDelegate中重写applicationDockMenu方法

    - (NSMenu *)applicationDockMenu:(NSApplication *)sender {
    NSMenu *menu = [[NSMenu alloc] initWithTitle:@"dock menu"];
    NSMenuItem *item1 = [[NSMenuItem alloc] initWithTitle:@"item 1" action:@selector(menuClick) keyEquivalent:@""];
    item1.target = self;
    NSMenuItem *item2 = [[NSMenuItem alloc] initWithTitle:@"item 2" action:@selector(menuClick) keyEquivalent:@""];
    item2.target = self;

    [menu addItem:item1];
    [menu addItem:item2];

    // 添加二级菜单
    NSMenu *menu2 = [[NSMenu alloc] initWithTitle:@"sub menu"];
    NSMenuItem *itemA = [[NSMenuItem alloc] initWithTitle:@"itemA" action:@selector(menuClick) keyEquivalent:@""];
    itemA.target = self;
    NSMenuItem *itemB = [[NSMenuItem alloc] initWithTitle:@"itemB" action:@selector(menuClick) keyEquivalent:@""];
    itemB.target = self;
    [menu2 addItem:itemA];
    [menu2 addItem:itemB];
    // 二级菜单放在指定item上
    [menu setSubmenu:menu2 forItem:item2];

    return menu;
    }
-------------本文结束感谢您的阅读-------------
坚持原创技术分享,您的支持将鼓励我继续创作!

欢迎关注我的其它发布渠道