Как изменить заголовок NSMenuItem (войти в систему)

Я удивлен, что об этом еще не спрашивали:

Но как можно изменить NSMenuItem название в NSStatusBar меню. Когда пользователь входит в систему, я хочу, чтобы пункт меню сказал выход. Я пытался создать выход, чтобы изменить мой NSMenuItem как бы ярлык или что-то.

AppDelegate.h

@property (retain) IBOutlet NSMenuItem *loginItem;

AppDelegate.m

[loginItem setTitle:@"Logout"];

Но это не сработало.

Единственное, что мне удалось сделать, это удалить старые NSMenuItem, затем добавьте новый, но он просто добавит его внизу. Это единственный способ сделать это, чтобы удалить все пункты меню, а затем повторно добавить их?? Это кажется очень неэффективным.

2 ответа

Решение

Метод, который вы описываете, должен работать, хотя, в целом, сохраняя IBOutlet s для всех ваших пунктов меню может быть утомительным. (Если ваше решение не работает, убедитесь, что IBOutlet на самом деле подключен в файл пера, и убедитесь, что вы устанавливаете заголовок в соответствующее время. Если вы пытаетесь установить его в вашем контроллере 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

В файле пера delegate выход из statusItemMenu установлен на 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/NSStatusBarFinagler

Вам не нужно подключать свой пункт меню, просто попробуйте это..

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. 
Другие вопросы по тегам