Skip to content

Instantly share code, notes, and snippets.

@swhitty
Created May 6, 2021 03:07
Show Gist options
  • Save swhitty/e2c12bcc6c6b24adb6d384dad7920ed3 to your computer and use it in GitHub Desktop.
Save swhitty/e2c12bcc6c6b24adb6d384dad7920ed3 to your computer and use it in GitHub Desktop.
import Combine
// `UIScheduler` eagerly executes actions on the current queue if
// it is the main thread, avoiding unnecessary async behaviour.
// If the current queue is not the main thread, then the action is
// then scheduled on the main queue asynchonously.
//
// `DispatchQueue` schedulers execute all actions asynchronously.
//
struct UIScheduler: Scheduler {
static let shared = UIScheduler()
private let queue: DispatchQueue
private init(queue: DispatchQueue = .main) {
queue.setSpecific(key: queueKey, value: queueIdentifier)
self.queue = queue
}
var now: DispatchQueue.SchedulerTimeType { queue.now }
var minimumTolerance: DispatchQueue.SchedulerTimeType.Stride { queue.minimumTolerance }
func schedule(options: DispatchQueue.SchedulerOptions?, _ action: @escaping () -> Void) {
if queue.getSpecific(key: queueKey) == queueIdentifier {
action()
} else {
queue.schedule(action)
}
}
func schedule(after date: DispatchQueue.SchedulerTimeType, tolerance: DispatchQueue.SchedulerTimeType.Stride, options: DispatchQueue.SchedulerOptions?, _ action: @escaping () -> Void) {
queue.schedule(after: date, tolerance: tolerance, options: nil, action)
}
func schedule(after date: DispatchQueue.SchedulerTimeType, interval: DispatchQueue.SchedulerTimeType.Stride, tolerance: DispatchQueue.SchedulerTimeType.Stride, options: DispatchQueue.SchedulerOptions?, _ action: @escaping () -> Void) -> Cancellable {
queue.schedule(
after: date,
interval: interval,
tolerance: tolerance,
options: nil,
action
)
}
private let queueKey = DispatchSpecificKey<UInt8>()
private let queueIdentifier: UInt8 = 0
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment