8

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

但是如何更改菜单NSMenuItem中的标题。NSStatusBar当用户登录时,我希望菜单项说注销。我曾尝试创建一个出口来修改我NSMenuItem的标签或其他东西。

AppDelegate.h

@property (retain) IBOutlet NSMenuItem *loginItem;

AppDelegate.m

[loginItem setTitle:@"Logout"];

但这没有用。

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

4

2 回答 2

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

在 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;
}

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

于 2013-01-17T04:51:26.593 回答
1

你不需要连接你的菜单项,试试这个..

NSMenuItem *menuItem = (NSMenuItem*) sender;
    NSString *menuString = menuItem.title;

    if ([menuString isEqualToString:@"Login"]) 
{

            [menuItem setTitle:@"LogOut"];
}

NSMenuItem menuItem = (NSMenuItem ) 发送者;

     this line automatically collect the menu items in your app. 
于 2013-01-17T04:35:00.553 回答