Re: how to prevent TableView update on key repeat?
Re: how to prevent TableView update on key repeat?
- Subject: Re: how to prevent TableView update on key repeat?
- From: Marc Respass <email@hidden>
- Date: Fri, 04 May 2012 11:25:21 -0400
El may 4, 2012, a las 3:19 a.m., Quincey Morris escribió:
> On May 3, 2012, at 19:38 , Graham Cox wrote:
>
>> You probably should do this as your last line:
>>
>> [self performSelector:<blah> withObject:nil afterDelay:[NSEvent keyRepeatInterval] + 0.1];
>>
>> because the key repeat rate is set by the user in the "Keyboard" system preferences and can change.
>
> I see your logic here, but I think this isn't the optimal answer.
>
> On the one hand, you want the delay to be as short as possible. Let's say the keyboard repeat interval is 0.83 as Marc reported. With the above delay, the user might have to wait more than 0.93 secs to see the detail view *start* to update, even after a single isolated keypress. From this point of view, the best delay is the shortest. From this point of view, the best delay is 0.
>
> On the other hand, you want the delay to be as long as possible. We're dealing with a situation where the time to update the detail view is greater than the repeat interval. Let's say it takes 1.0 secs to do the update. Once the update (the performed method) starts to execute, then even the next keystroke is delayed for the full 1.0 secs, not just subsequent detail updates. This is a kind of freeze from the user's point of view, hence the pressure to defer it as long as possible.
>
> [Note: The other scenario to consider here is that the user might mash an arrow key rather than hold it down. The key repeat interval seems irrelevant in this case, another reason not to use it.]
>
> Statistically (that is, over a wide variety of key presses), the time-alignment of keypresses and updates would [I think] be randomly distributed, so the *expected* completion time after the last keypress in a series would be the total of:
>
> -- half of the 1.0 sec freeze, or 0.5 secs, resulting from intermediate non-canceled updates occurring at "random" times
> -- the performSelector delay, which must happen before the last update
> -- the full 1.0 sec freeze of the last update.
>
> That's a really long time -- 1.5 secs with no delay, or 2.33 secs with your suggested repeat-interval-based delay.
>
> To summarize, therefore, the expected update completion time would be:
>
> -- after a single keystroke, 'performSelector delay plus update freeze time'
>
> -- after multiple keystrokes (whether repeated or mashed singly), 'performSelector delay plus 1.5 * update freeze time'
>
> Since I can't control the update freeze time, I'd *really* want to set the performSelector delay to 0 -- certainly not 0.93.
>
>
> My thinking about the delay of 0.1 secs (instead of 0) was do with trying to ensure that the detail update didn't start if another event was about to happen that might get delayed due to the update freeze starting first. On second thoughts, though, I think my reasoning was flawed, so I'm back to thinking a delay of 0 is the best solution.
When I set the delay to zero, there is no delay. My selector is called immediately as if I didn't change anything. It seems that the selector must be set to fire just after the key repeat because tableViewSelectionDidChange: is going to be called at the keyRepeatInterval. By setting the interval to [NSEvent keyRepeatInterval] + 0.01; everything works fabulously if your key repeat rate is high because the selection change won't fire until the interval no matter what. When the repeat interval is very slow, the selection changes very slowly no matter how it changes (click, type to select, repeatedly hitting up/down).
I added this to determine what the delay interval should be
NSTimeInterval delayInterval = 0.0;
NSEvent *event = [NSApp currentEvent];
if(event != nil && [event type] == NSKeyDown && [event isARepeat])
{
delayInterval = [NSEvent keyRepeatInterval] + 0.01;
}
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(selectionDidChange) object:nil];
[self performSelector:@selector(selectionDidChange) withObject:nil afterDelay:delayInterval];
The objection to that was that I don't know what the current event is. If that is true, when [NSApp currentEvent] is useful? It seems that the current event will be the one that caused tableViewSelectionDidChange: to be called.
In my limited testing with different key repeat rates, everything works fine. I'm using a standard NSTableView. If my key repeat is very slow, then selection change is slow and updates wait until I lift the key. Type to select works fine. Clicking works fine. Repeatedly hitting up/down works fine. I don't see any problem with this but I've already not seen things so thoughts on this solution are appreciated.
Thanks again
Marc
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden