Created
October 5, 2017 17:34
-
-
Save zyuanming/5bcffe91e1516b5ea1bd01c7cfc869e7 to your computer and use it in GitHub Desktop.
UIKonf 2017 – Day 1 –Thomas Visser – Reactive Programming From Scratch
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
| 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