9

I have a NSMenu with dynamically added NSMenuItems. The NSMenu is not refreshing properly while it's kept open. I am calling NSMenu update method in NSEventTrackingRunLoopModes.

I have implemented following methods to update NSMenu.

- (void)menuNeedsUpdate:(NSMenu *)menu {
for (NSInteger index = 0; index < count; index++)
    [self menu:menu updateItem:[menu itemAtIndex:index] 
                       atIndex:index 
                  shouldCancel:NO];
}

- (BOOL)menu:(NSMenu *)menu updateItem:(NSMenuItem *)item atIndex:(NSInteger)index shouldCancel:(BOOL)shouldCancel`

- (NSInteger)numberOfItemsInMenu:(NSMenu *)menu
Vinpai
  • 1,689
  • 3
  • 16
  • 18
  • I have a similar question. I'd like to update the NSMenu while it is open depending on whether the user is pressing the option key. The behavior I need to what Xcode does when the Product menu is open and the option key is pressed. Can this be done with the built-in NSMenu methods? – pjg Jul 02 '19 at 02:09

3 Answers3

7

Updating the menu items in NSEventTrackingRunLoopMode solved this issue.

Vinpai
  • 1,689
  • 3
  • 16
  • 18
5

I am dynamically populating menu items in a timer and NSMenu is not updating while it's open.

Make sure to have the timer fire on the respective run mode:

[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

You might only have it fire on NSDefaultRunLoopMode right now.

soryu2
  • 144
  • 5
  • 1
    I have tried using NSRunLoopCommonModes but still I am getting Menu refreshing issue while it's open – Vinpai Apr 14 '12 at 09:14
0

You have left out a bunch of the code. However, you aren't supposed to call -menu:updateItem:atIndex:shouldCancel:. That's a method that you're supposed to implement and the framework is supposed to call it.

Also, generally you're only suppose to implement either -menuNeedsUpdate: or both of -numberOfItemsInMenu: and -menu:updateItem:atIndex:shouldCancel:. Implementing all three doesn't make much sense. You implement the former if you can build the menu immediately. You implement the latter two if building the menu will take some time.

Finally, all of those methods are documented as being called "when a menu is about to be displayed". I'm not terribly surprised that they're not called repeatedly while the menu is open.

If you know the menu needs to be updated, you can try invoking -[NSMenu update]. That may provoke it to call your delegate methods. I'm pretty sure you can also just call the methods on NSMenu and NSMenuItem to modify the menu, without waiting for your delegate to be called.

Ken Thomases
  • 88,520
  • 7
  • 116
  • 154
  • `[NSMenu update]` doesn't call any delegate methods. I am dynamically populating menu items in a timer and NSMenu is not updating while it's open. – Vinpai Apr 13 '12 at 12:37
  • It's not updating even if you invoke things like `-[NSMenu addItem:]` or `-[NSMenuItem setTitle:]` in response to your timer? I'm sure I've seen menus update while they're open, so it's possible. – Ken Thomases Apr 13 '12 at 12:44
  • @KenThomases The first party OS clock does that (its more noticeable if you display seconds). – Eliza Wilson Nov 10 '13 at 03:01