On May 4, 2012, at 08:25 , Marc Respass wrote:

> When I set the delay to zero, there is no delay. My selector is called 
> immediately as if I didn't change anything.


Not exactly. Consider what happens when you mash the arrow key. Thus, there 
might be multiple (normal) key events queued. The selector won't actually be 
performed until they're *all* dequeued from the main event queue (because, 
presumably, any queued perform is further down the queue).

At that point, no subsequent key events can be dequeued until the update has 
run. IOW, there's a slight hitch every time the event queue empties of key 
events. That's *much* better than the original (non-performSelector) approach, 
because at least some of the updates are suppressed.

So a delay of 0 helps key-mashers (and doesn't penalize other methods of 
selection change, such a click). It doesn't help the key-repeat case very much. 
Trying to solve the repeat case like this is a neat idea:

> 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];

but it still has the drawback that there's an additional '[NSEvent 
keyRepeatInterval] + 0.01 + timeToUpdateDetailView' delay after the last one, 
during the latter part of which the user is frozen out of the UI.

Let's say, though, that you wanted to pursue the approach that the above code 
represents. In that case, I probably *would* subclass the table view, and 
override keyDown: and keyUp:. You could simply set a flag at key down and clear 
it at key up, and use that information to control the way the performSelectors 
are timed. (It's still something of a hack, but at least it keeps the NSEvent 
details out of your selectionDidChange code.)

However, once you get to this level of complexity, then it's probably 
worthwhile to spend your effort on moving the time-consuming part of the update 
process into a background thread instead. That would solve the problem for 
realz, letting keys repeat at their proper rate and letting updates happen as 
soon as they're ready, without freezes and artificial delays.

> 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.

It's useful when you know that you dequeued the last event and that you haven't 
dequeued another one since. In this case, you know that the table view dequeued 
a key event, but you don't know what it did after that. It *might* have created 
a background async GCD block to do the selection pre-processing, then executed 
a completion handler on the main thread to send the notification that triggered 
your method. Or, it *might* have looked ahead in the main event queue and 
dequeued some event.

Even if you determined empirically that [NSApp currentEvent] gives you the key 
event, you can't be sure it will continue to do so in future frameworks 
versions.


_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to