Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>The problem here is that you need your callback to get triggered even in menu tracking mode.</p> <p>For example, -[NSTask waitUntilExit] "polls the current run loop using NSDefaultRunLoopMode until the task completes". This means that it won't get run until after the menu closes. At that point, scheduling updateTheMenu to run on NSCommonRunLoopMode doesn't help—it can't go back in time, after all. I believe that NSNotificationCenter observers also only trigger in NSDefaultRunLoopMode.</p> <p>If you can find some way to schedule a callback that gets run even in the menu tracking mode, you're set; you can just call updateTheMenu directly from that callback.</p> <pre><code>- (void)updateTheMenu { static BOOL flip = NO; NSMenu *filemenu = [[[NSApp mainMenu] itemAtIndex:1] submenu]; if (flip) { [filemenu removeItemAtIndex:[filemenu numberOfItems] - 1]; } else { [filemenu addItemWithTitle:@"Now you see me" action:nil keyEquivalent:@""]; } flip = !flip; } - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { NSTimer *timer = [NSTimer timerWithTimeInterval:0.5 target:self selector:@selector(updateTheMenu) userInfo:nil repeats:YES]; [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; } </code></pre> <p>Run this and hold down the File menu, and you'll see the extra menu item appears and disappears every half second. Obviously "every half second" isn't what you're looking for, and NSTimer doesn't understand "when my background task is finished". But there may be some equally simple mechanism that you can use.</p> <p>If not, you can build it yourself out of one of the NSPort subclasses—e.g., create an NSMessagePort and have your NSTask write to that when it's done.</p> <p>The only case you're really going to need to explicitly schedule updateTheMenu the way Rob Keniger described above is if you're trying to call it from outside of the run loop. For example, you could spawn a thread that fires off a child process and calls waitpid (which blocks until the process is done), then that thread would have to call performSelector:target:argument:order:modes: instead of calling updateTheMenu directly.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload