Skip to content

Instantly share code, notes, and snippets.

@atimca
Created April 2, 2020 15:50
Show Gist options
  • Save atimca/51c83f4c9161fc36bed340b02e605d09 to your computer and use it in GitHub Desktop.
Save atimca/51c83f4c9161fc36bed340b02e605d09 to your computer and use it in GitHub Desktop.
A tiny realization of a reactive approach.
import PlaygroundSupport
import Foundation
class WeakRef<T> where T: AnyObject {
private(set) weak var value: T?
init(value: T?) {
self.value = value
}
}
class Observer<Element> {
private let on: (Element) -> Void
init(_ on: @escaping (Element) -> Void) {
self.on = on
}
func on(_ event: Element) {
on(event)
}
}
class Observable<Element> {
typealias WeakObserver = WeakRef<Observer<Element>>
private var observers: [WeakObserver] = []
private let isolationQueue = DispatchQueue(label: "", attributes: .concurrent)
private var _value: Element
var value: Element {
get {
isolationQueue.sync { _value }
}
set {
isolationQueue.async(flags: .barrier) {
self._value = newValue
self.observers.forEach { $0.value?.on(newValue) }
}
}
}
private var transform: ((Element) -> Element)?
init(value: Element) {
self._value = value
}
func subscribe(onNext: @escaping (Element) -> Void) -> Observer<Element> {
let transform = self.transform ?? { $0 }
let observer = Observer<Element> { element in
onNext(transform(element))
}
observers.append(.init(value: observer))
return observer
}
func map(_ transform: @escaping (Element) -> Element) -> Observable<Element> {
self.transform = transform
return self
}
}
let observable = Observable<Int>(value: 0)
let observer = observable
.map { $0 + 1 }
.subscribe { print($0) }
for i in 1...5 {
observable.value = i
}
// 2, 3, 4, 5, 6
PlaygroundPage.current.needsIndefiniteExecution = true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment