Last active
August 21, 2020 04:43
-
-
Save myobie/5eec6ec9afaf2b80f1efa930f5d92117 to your computer and use it in GitHub Desktop.
GCD Timer using DispatchSourceTimer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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