如何更改NSMenuItem标题(登录注销)

urb*_*der 5 cocoa objective-c nsmenuitem

我很惊讶,这还没有被问到:

但是如何改变菜单中的NSMenuItem标题呢NSStatusBar?当用户登录时,我希望菜单项说出注销.我试过创建一个插座来修改我NSMenuItem的标签或其他东西.

AppDelegate.h

@property (retain) IBOutlet NSMenuItem *loginItem;

AppDelegate.m

[loginItem setTitle:@"Logout"];

但那没有用.

我唯一能做的就是删除旧的NSMenuItem,然后添加一个新的,但它只是将它添加到底部.是唯一的方法来删除每个菜单项然后重新添加它们?这似乎非常低效.

NSG*_*God 4

您描述的方法应该有效,但一般来说,IBOutlet为所有菜单项保留 s 可能很乏味。(如果您的解决方案不起作用,请确保IBOutlet在 nib 文件中实际连接,init确保您在适当的时间设置标题。例如,如果您尝试在控制器的方法中设置它,这还为时过早,并且插座尚未连接:将方法移至awakeFromNib或类似。

从长远来看,更好的方法是使用<NSMenuDelegate>协议和NSMenuValidation(非正式)协议来动态(和延迟)更新菜单项。

例如,定义控制器类如下:

@interface MDAppDelegate : NSObject <NSApplicationDelegate, NSMenuDelegate>


@property (strong) NSStatusItem *statusItem;

@property (weak) IBOutlet NSWindow *window;

@property (weak) IBOutlet NSMenu *statusItemMenu;
@property (weak) IBOutlet NSMenuItem *toggleLoginLogoutMenuItem;

@property (weak) IBOutlet NSTextField *statusField;
@property (weak) IBOutlet NSTextField *progressField;
@property (weak) IBOutlet NSProgressIndicator *progressIndicator;

@property (assign) BOOL loggedIn;

- (IBAction)toggleLoginLogout:(id)sender;

@end
Run Code Online (Sandbox Code Playgroud)

在nib文件中,delegateoutletstatusItemMenu被设置为MDAppDelegate控制器类。这确保了该类位于响应程序链中,并允许它与验证菜单项MDAppDelegate一起工作。

然后你可以像下面这样实现你的 .m :

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    _statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
    _statusItem.menu = _statusItemMenu;
    _statusItem.title = NSLocalizedString(@"NSStatusItem", @"");
    [self updateLoggedInStatus];
}
- (void)updateLoggedInStatus {
    [self.statusField setStringValue:(self.loggedIn ? @"Logged in" : @"Logged out")];
}
- (IBAction)toggleLoginLogout:(id)sender {
    [self performSelector:@selector(finishFakeLoginLogout:)
                         withObject:nil afterDelay:2.0];
}
- (void)finishFakeLoginLogout:(id)sender {
    self.loggedIn = !self.loggedIn;
    [self updateLoggedInStatus];
}
- (void)menuNeedsUpdate:(NSMenu *)menu {
#if MD_DEBUG
    NSLog(@"[%@ %@]", NSStringFromClass([self class]), NSStringFromSelector(_cmd));
#endif
}
- (BOOL)validateMenuItem:(NSMenuItem *)menuItem {
#if MD_DEBUG
    NSLog(@"[%@ %@]", NSStringFromClass([self class]), NSStringFromSelector(_cmd));
#endif
    SEL action = menuItem.action;
    if (action == @selector(toggleLoginLogout:)) {
        [menuItem setTitle:(self.loggedIn ? @"Logout" :@"Login")];
    }
    return YES;
}
Run Code Online (Sandbox Code Playgroud)

示例项目:http://github.com/NSGod/NSStatusBarFinagler