Skip to content

Instantly share code, notes, and snippets.

@zyuanming
Created October 5, 2017 17:34
Show Gist options
  • Select an option

  • Save zyuanming/5bcffe91e1516b5ea1bd01c7cfc869e7 to your computer and use it in GitHub Desktop.

Select an option

Save zyuanming/5bcffe91e1516b5ea1bd01c7cfc869e7 to your computer and use it in GitHub Desktop.
UIKonf 2017 – Day 1 –Thomas Visser – Reactive Programming From Scratch
var z = 0
let s = AnyIterator { () -> Int in
defer { z += 1 }
return z
}
for i in s.lazy.prefix(3) {
print(i)
}
typealias Observer<E> = (E) -> Void
typealias Disposable = () -> Void
class Observable<E> {
typealias SubscriptionHandler = (@escaping Observer<E>) -> Disposable
let handler: SubscriptionHandler
init(subscriptionHandler: @escaping SubscriptionHandler) {
self.handler = subscriptionHandler
}
func subscribe(_ observer: @escaping Observer<E>) -> Disposable {
return self.handler(observer)
}
}
let o = Observable<Int> { obs in
obs(1)
obs(2)
obs(3)
obs(4)
return {}
}
o.subscribe {
print($0)
}
func timer(delay: Int) -> Observable<Int> {
return Observable { obs in
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(delay)) {
obs(delay)
}
return {}
}
}
timer(delay: 360).subscribe { _ in
print("Your soft boiled egg is ready!")
}
extension Observable {
func map<U>(_ f: @escaping (E) -> U) -> Observable<U> {
return Observable<U> { observer in
self.subscribe { elem in
observer(f(elem))
}
}
}
}
extension Observable {
func share() -> Observable<E> {
var subscribed = false
var observers: [Observer<E>] = []
return Observable<E> { observer in
observers.append(observer)
if !subscribed {
self.subscribe { e in
for o in observers {
o(e)
}
}
subscribed = true
}
return {}
}
}
}
protocol ObservableProtocol {
associatedtype Element
func subscribe(_ observable: @escaping Observer<Element>) -> Disposable
}
extension Observable: ObservableProtocol { }
extension Observable where E: ObservableProtocol {
func flatten() -> Observable<E.Element> {
return Observable<E.Element> { observer in
var disposables: [Disposable] = []
let outerD = self.subscribe { innerObservable in
let innerD = innerObservable.subscribe(observer)
disposables.append(innerD)
}
disposables.append(outerD)
return {
for d in disposables { d() }
}
}
}
}
func response(url: URL) -> Observable<(Data, URLResponse)> {
return Observable { observer in
let t = URLSession.shared.dataTask(with: url) { d, r, e in
if let error = e {
print(error)
}
guard let data = d, let response = r else { return }
observer((data, response))
}
t.resume()
return {
t.cancel()
}
}
}
let uikonf = response(url: URL(string: "www.baidu.com/img/bd_logo1.png")!)
let disposable = uikonf.subscribe { data, response in
print(data)
}
class Box<Value> {
var value: Value
init(_ value: Value) {
self.value = value
}
}
class Subject<E>: Observable<E> {
let observers: Box<[Observer<E>?]>
init() {
let observers = Box<[Observer<E>?]>([])
self.observers = observers
super.init { observer in
let i = observers.value.count
observers.value.append(observer)
return {
observers.value[i] = nil
}
}
}
func send(_ newElement: E) {
for o in observers.value {
o?(newElement)
}
}
}
let buttonTaps = Subject<Void>()
let d = buttonTaps.map { _ -> Observable<(Data, URLResponse)> in
let url = URL(string: "https://www.baidu.com/")!
return response(url: url)
}.flatten().subscribe { (value) in
print(value.0)
}
buttonTaps.send(())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment