AWF4vk
AWF4vk

Reputation: 5890

NSRunLoop freezes with NSTimer and any input

For some reason when I push down (click and hold) on any control, the NSTimer in my App freezes and does not fire until I release the mouse button. It simply does not fire while I have the mouse pressed. This is fine for short periods, but it also freezes if I have a popup menu open, or a combobox dropped down.

I'm not sure if there is something I missed, but it seems like this is incorrect behavior.

I want to be able to click the down arrow of an NSPopUpButtonCell (or even click and hold an NSTableView) without the entire NSTimer freezing (which redraws an NSView).

Any comments / suggestions would be appreciated.

The NSTimer is added to the currentRunLoop with mode NSDefaultRunLoopMode.

Upvotes: 1

Views: 3847

Answers (3)

strange
strange

Reputation: 9724

Instead of adding two or more timers to different runloops or using multithreading (as you won't then be able to update the UI from another thread) simply add the timer to the NSRunLoopCommonModes:

NSTimer *myTimer = [NSTimer timerWithTimeInterval:RefreshInterval target:self selector:@selector(doWork) userInfo:nil repeats:YES];
  [[NSRunLoop currentRunLoop] addTimer:myTimer forMode:NSRunLoopCommonModes];

Upvotes: 8

Sam
Sam

Reputation: 2707

Assuming you're just dealing with one thread in your application, what you described is perfectly expected. By default, NSTimer's are added to the current NSRunLoop which, in your case, is also responsible for dealing with UI interaction. When it gets tied up with handling UI interaction, it can't check your timer and "fire" it.

A solution is to use multi-threading so as to avoid this tie-up. Here's a nice blog post on this very subject: http://blog.narent.com/?p=21

EDIT: See Dave's post for an alternative (and more elegant IMO) solution

Also see:

Upvotes: 0

Dave DeLong
Dave DeLong

Reputation: 243156

While the mouse is down, the run loop is in the NSEventTrackingRunLoopMode. Therefore, any event that's not received onto the EventTracking event queue won't be serviced until the runloop returns to the appropriate mode.

The way around this is to add the timer to the runloop for both modes (default and event tracking).

Upvotes: 8

Related Questions