Coalescing NSNotifications - objective-c

Is there any way when using coalescing notifications on NSNotificationQueues to control the time range?
I would like to coalesce e.g. for the next second, but as I understand the options available it's either immediately or on next run loop invocation or 'when idle'..
Any other way to e.g. coalesce over a longer time range?
I'm basically looking for a way to gather all user events (like pinch-to-zoom) over a small time range and launch an expensive operation only after the user apparently stopped zooming/etc.

You can schedule a NSTimer when the first notification comes in. When the next notification comes in, check your timer instance variable. If it is non-nil, ignore the notification. Otherwise start a fresh timer.
When the timer fires, clear your timer instance variable and launch your expensive operation.
An simpler alternative is to use performSelector:afterDelay: and cancelPreviousPerformRequestsWithTarget:selector:object:. The effect however is not the same. You will further delay your expensive operation each time a notification is received. If notifications come faster than the delay you set, the expensive operation will never run.

Related

NotesTimer causes the whole lotus client to flicker

I have a timer that talks to java objects through LS2J. It has only to call some getters of the java objects and to update the GUI with new values. This causes the GUI in iNotes Client to show the "Busy" cursor very shortly when the timer ticks. I is really annoying because it occurs even when another window is open and even in the designer.
I actually have to expect that the functionality in the timer event will get more complicated in the future, so I don't want to solve the problem by making my handler lighter.
Is there a way to tell iNotes client not to show this cursor or even an alternative way to make this regular check without timers?
The NotesTimer class in Notes client (not iNotes) does take over the foreground when it triggers, so there will be a bit of a delay if you do something that takes time to execute. It's possible to set up the Notes client to execute background scheduled agents in local database replicas, so that might be an option. You can to the heavy lifting in background and deposit the results somewhere -- say, in a profile document -- that can be accessed quickly by the UI code.
Alternately, you could try a XPages in the client application. I believe it can do partial refreshes while other stuff is going on.
For the record, I simplified the functionality of the Java call by preparing the data so that the timer only has to read the results. I also made the timer run every 3 seconds instead of 1.
Now I don't see any flicker!

Suspending and modifying NServiceBus saga timeouts

I have a saga which represents a long-running work assignment process of a "Person" to a "Case". Several events may kick it off, and at the end of the process we have an assignment confirmation, at which point the saga completes and the Person is assigned to the Case. I would like to have a timeout for this saga so that we don't wait indefinitely for confirmation - definitely a valid business use case. No difficulties there - fairly vanilla.
The twist is that this assignment process can be blocked if someone puts the Case on hold. I have an event I can subscribe to so my assignment saga knows the Case is on hold, but unless I adjust the timeout or suspend it in some way, the assignment saga will likely time out before the Case hold is released. It doesn't make business sense to do this, so I basically want to stop the timeout clock until some other event comes in.
This same issue was mentioned here a couple years ago. Is this still not possible or are there new features in v3.x that would allow it? If not, is it a planned feature?
Thanks!
Why not remove the timeout altogether for the instance when your case is put on hold? Your saga maintains the state of the case and the calculated time when the case would have been due. This could have been set when you created the first timeout. When the case is reactivated, simply calculate the difference in time from the reactivation and the saved "deadline", and create a new timeout for that instance with the difference. You may also want to take into account the time the case was on hold and set a new deadline which you would save back to the instance state.
I don't think there is a way to tab directly to the timer and put the timeout message "on-hold"
I would have that logic inside the timeout handler on the saga. Check if the case is on hold and request another timeout without ending the saga.

Notification after user becomes idle on OS X?

What's the best way of detecting when a user has been idle for X amount of time, and then detect when the user becomes immediately active?
I know there's NSWorkspace which provides will/did sleep/wake notifications, but I can't rely on that because the sleep setting is usually about ~15 minutes to never. I need to be able to detect if the user's been idle for ~1-2 minutes.
This answer provides a way to get the idle time. I'd like to avoid polling if possible.
Polling is your only option, to my knowledge. As user1118321 points out, polling every O(minutes) is unlikely to cause any problems, performance or otherwise.
If your app has a GUI and receives UI events anyway, you could install a handler via +[NSEvent addLocalMonitorForEventsMatchingMask:handler:] that resets your timer on each event. That'll help reduce if not eliminate polls when the user is consistently active, in your own app at least.
Once you've determined that the user has been idle long enough, you could then install a global event tap to watch for the next event. See for example -[NSEvent addGlobalMonitorForEventsMatchingMask:handler:].
Note: you should use CGEventSourceSecondsSinceLastEventType if at all possible rather than poking into the IO registry. It's a formal, supported API and may be more efficient. Not to mention it's way simpler. There's also UKIdleTimer though it relies on Carbon, so may not be applicable.

Is there a way to set so that CLLocation do not update too often?

Obviously I need to update accurately. However not more often than once every 1 minute I think.
See example use of CLLocationManager and a handler class to do what you are asking. Rather than a timer, it sets up a handler to respond to location events received, checks the accuracy and time passed since previous event, then sends out a notification based on your requirements.
The frequency of your response action is configurable as often as you require.
It works in the background, with battery saving configuration options.
See the code here TTLocationHandler
You may also benefit from some of the discussion in this question thread Invoke get current coordinates every few seconds without NSTimer
Once you have position update you can:
Turn off updating
Start a timer for about 1 minute
Timer turns on updating
Done.

How to not get NSSearchField freezing?

I've got a NSSearchField, whose action method does all the searching stuff, by analyzing the sender argument (string).
Now the searching stuff (feeding a large array) is kind of CPU intensive, which lets my search field freeze for some seconds.
In other cases i'd detach another NSThread to prevent my GUI from freezing. But in this case that is not possible, because I would detach another ("search") thread everytime the user enters another letter in the search field.
Is there another way of keeping my NSSearchField from freezing?
BTW: My guess is NO, because even the Developoer Documentation's seach field freezes all the time :)
I use GCD. I use an async queue, and the job periodically checks if the current search pattern has changed from what it was called with, and bails if it has. This seems to work quite well.
Can't you use setSendsWholeSearchString: to stop it searching as letters are typed?
Set an NSTimer every time the user types something.
If there's a timer already set, invalidate or reschedule it.
That way, you only get called upon to refresh the search every N seconds, however fast the user types.