2013-01-17 14 views
5

Im ngạc nhiên rằng điều này đã chưa được hỏi:Làm thế nào để thay đổi NSMenuItem Tiêu đề (Đăng nhập để Logout)

Nhưng làm thế nào để đi về việc thay đổi tiêu đề NSMenuItem trong menu NSStatusBar. Khi người dùng đăng nhập, tôi muốn mục menu nói đăng xuất. Tôi đã cố gắng tạo một lối thoát để sửa đổi NSMenuItem của tôi như một nhãn hiệu hoặc một thứ gì đó.

AppDelegate.h

@property (retain) IBOutlet NSMenuItem *loginItem;

AppDelegate.m

[loginItem setTitle:@"Logout"];

Nhưng đó didnt làm việc.

Điều duy nhất mà tôi có thể làm là xóa cũ NSMenuItem, sau đó thêm một hình mới, nhưng nó sẽ chỉ thêm nó vào cuối. Là cách duy nhất để làm điều này để loại bỏ tất cả các mục trình đơn sau đó lại thêm chúng? Điều đó có vẻ rất không hiệu quả.

+1

Không có gì trong ví dụ của bạn để đề nghị bạn đang làm này không chính xác là. Nhưng bạn có thực sự kết nối 'IBOutlet' của bạn với mục menu không? – trudyscousin

Trả lời

4

Phương pháp bạn mô tả sẽ hoạt động, tuy nhiên, giữ cho tất cả các mục menu của bạn có thể tẻ nhạt. (Nếu giải pháp của bạn không hoạt động, hãy đảm bảo rằng IBOutlet thực sự được kết nối trong tệp nib, đảm bảo rằng bạn đang đặt tiêu đề vào thời điểm thích hợp. Nếu bạn đang cố gắng đặt tiêu đề trong bộ điều khiển init phương pháp, ví dụ, quá sớm và các cửa hàng chưa được kết nối: di chuyển phương thức đến awakeFromNib hoặc tương tự.

Cách tiếp cận tốt hơn về lâu dài là sử dụng giao thức <NSMenuDelegate>NSMenuValidation (không chính thức)) giao thức để cập nhật các mục menu động (và lazily)

Ví dụ: xác định lớp trình điều khiển của bạn như sau:

@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 

Trong tệp nib, cổng delegate của statusItemMenu được đặt thành lớp điều khiển MDAppDelegate. Điều đó đảm bảo rằng lớp MDAppDelegate nằm trong chuỗi trả lời và cho phép nó hoạt động với validating the menu items.

Sau đó, bạn có thể thực hiện .m của bạn như sau:

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

dự án mẫu: http://github.com/NSGod/NSStatusBarFinagler

1

Bạn không cần phải kết nối mục trình đơn của bạn chỉ cần cố gắng này ..

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

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

      [menuItem setTitle:@"LogOut"]; 
} 

NSMenuItem MenuItem = (NSMenuItem) người gửi;

 this line automatically collect the menu items in your app.