Skip to content

Instantly share code, notes, and snippets.

@myobie
Last active August 21, 2020 04:43
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save myobie/5eec6ec9afaf2b80f1efa930f5d92117 to your computer and use it in GitHub Desktop.
Save myobie/5eec6ec9afaf2b80f1efa930f5d92117 to your computer and use it in GitHub Desktop.
GCD Timer using DispatchSourceTimer
import Cocoa
import Combine
class Timer: Cancellable, Publisher {
enum Error: Swift.Error {
case cancelled
}
typealias Output = Never
typealias Failure = Error
private let source: DispatchSourceTimer
private let subject = PassthroughSubject<Output, Failure>()
init(_ interval: DispatchTimeInterval, leeway: DispatchTimeInterval = .milliseconds(300)) {
self.source = DispatchSource.makeTimerSource()
let deadline = DispatchTime.now().advanced(by: interval)
source.schedule(deadline: deadline, repeating: .never, leeway: leeway)
source.setEventHandler { self.fire() }
source.activate()
}
func fire() {
print("fire")
subject.send(completion: .finished)
}
func cancel() {
print("cancel")
source.cancel()
subject.send(completion: .failure(.cancelled))
}
func receive<S>(subscriber: S) where S : Subscriber, Failure == S.Failure, Output == S.Input {
subject.receive(subscriber: subscriber)
}
deinit {
print("deinit")
cancel()
}
}
let sub = Timer(.seconds(3)).sink(receiveCompletion: { event in
switch event {
case .finished:
print("finished!")
case .failure:
print("cancelled!")
}
}, receiveValue: { _ in })
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment