Created
December 2, 2016 05:50
-
-
Save jverkoey/39b510e3bedffa5296dc7132df70fa66 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
| protocol Observer { | |
| associatedtype Value | |
| func next(_ value: Value) -> Void | |
| } | |
| class Subscription { | |
| init(_ unsubscribe: (() -> Void)? = nil) { | |
| _unsubscribe = unsubscribe | |
| } | |
| func unsubscribe() { | |
| _unsubscribe?() | |
| _unsubscribe = nil | |
| } | |
| private var _unsubscribe: (() -> Void)? | |
| } | |
| class Observable<T> { | |
| typealias Value = T | |
| let creator: (AnyObserver<Value>) -> Subscription | |
| init(_ creator: @escaping (AnyObserver<Value>) -> Subscription) { | |
| self.creator = creator | |
| } | |
| func subscribe<O: Observer>(_ observer: O) -> Subscription where O.Value == T { | |
| let observer = AnyObserver(observer: observer) | |
| listeners.add(observer) | |
| if listeners.count == 1 { | |
| // Is down-stream reference, so must be weak. | |
| subscription = creator(AnyObserver { [weak self] in self?.dispatchNext($0) }) | |
| } | |
| return Subscription({ | |
| self.listeners.remove(observer) | |
| if self.listeners.count == 0 { | |
| self.subscription?.unsubscribe() | |
| } | |
| }) | |
| } | |
| func subscribe(next: @escaping (Value) -> Void) -> Subscription { | |
| let observer = AnyObserver<Value>(next) | |
| return subscribe(observer) | |
| } | |
| private func dispatchNext(_ value: Value) { | |
| for listener in listeners { | |
| (listener as! AnyObserver<Value>).next(value) | |
| } | |
| } | |
| private var listeners = NSMutableOrderedSet() | |
| private var subscription: Subscription? | |
| } | |
| // Swift-specific | |
| class AnyObserver<T>: Observer { | |
| typealias Value = T | |
| private let _next: (Value) -> Void | |
| init<O: Observer>(observer: O) where O.Value == Value { | |
| _next = { observer.next($0) } | |
| } | |
| init(_ next: @escaping (Value) -> Void) { | |
| _next = next | |
| } | |
| func next(_ value: Value) { | |
| _next(value) | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment