Skip to content

Instantly share code, notes, and snippets.

@danielctull
Last active March 22, 2018 11:52
Show Gist options
  • Save danielctull/5629a04030a1a3c329b472a998c707c7 to your computer and use it in GitHub Desktop.
Save danielctull/5629a04030a1a3c329b472a998c707c7 to your computer and use it in GitHub Desktop.
A small class to coalesce multiple calls to trigger a block once.
import Foundation
/// This manages coalescing multiple calls per frame into a
/// single execution of the given block.
final class Coalescer {
private let notificationCenter: NotificationCenter
private let notificationQueue: NotificationQueue
private let notificationName = Notification.Name(rawValue: "CoalescingNotification")
/// Create a coalescer.
///
/// The given block will be run once after one or more calls to
/// coalesce() happen in a single frame.
///
/// - Parameter block: The block to run.
init(block: @escaping () -> ()) {
// We use our own private notification center and notification
// queue so as not to pollute the global default center and queue.
// This also means multiple Coalescers can co exist firing the same
// notification name, without triggering each other.
notificationCenter = NotificationCenter()
notificationQueue = NotificationQueue(notificationCenter: notificationCenter)
notificationCenter.addObserver(forName: notificationName, object: nil, queue: nil) { (notification) in
block()
}
}
/// Call this to trigger the execution of the block given when instantiated.
func coalesce() {
let notification = Notification(name: notificationName)
// We use notification queue to enqueue a notification. The
// coalesce mask will mean that the notification is only
// processed once for each individual name.
notificationQueue.enqueue(notification, postingStyle: .asap, coalesceMask: .onName, forModes: nil)
}
}
@Abizern
Copy link

Abizern commented Oct 9, 2017

Nice, but since the initialiser doesn't actually take any parameters used for setting the centre and the queue, why not just initialise them inline?

@danielctull
Copy link
Author

I don't think you could initialise the notificationQueue using the notificationCenter property, so they need to be done in the init?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment