|
import Foundation |
|
import PlaygroundSupport |
|
import RxSwift |
|
|
|
PlaygroundPage.current.needsIndefiniteExecution = true |
|
|
|
/// dictionary of (id: shared Observable) |
|
var store: [String: Any] = [:] |
|
|
|
/// makeSequence return an existing shared sequence identified by `id` |
|
/// or create and store a new one |
|
/// for the purpose of this playground we just create dummy interval sequences |
|
/// but in real code this could be observable emitting data from a websocket, a firebase node... |
|
func makeSequence(id: String, period: RxTimeInterval) -> Observable<Int> { |
|
if let seq = store[id] as? Observable<Int> { |
|
print("store:reuse \(id)") |
|
return seq |
|
} |
|
|
|
print("store:create \(id)") |
|
let seq = Observable<Int> |
|
.interval(period, scheduler: MainScheduler.instance) |
|
.do(onDispose: { |
|
print("store:remove \(id)") |
|
store.removeValue(forKey: id) |
|
}) |
|
|
|
let shared = seq.shareReplay(1) |
|
store[id] = shared |
|
return shared |
|
} |
|
|
|
/// test |
|
/// this simulate a sequence observing a model |
|
/// where we need to flatMap to get a nested model attached |
|
let _ = makeSequence(id: "model", period: 1.0) |
|
.flatMapLatest { (index: Int) -> Observable<(game: Int, creator: Int)> in |
|
// received some model updates... |
|
let seq = makeSequence(id: "nested-model", period: 0.2) |
|
|
|
// create a subscription that we will dispose |
|
// when the returned sequence dispose, but in an async fashion. |
|
// This way, we get a chance to reuse the same shared sequence |
|
// on the next run of this flatMapLatest block |
|
let subscription = seq.subscribe() |
|
return seq |
|
.do( |
|
onDispose: { DispatchQueue.main.async { subscription.dispose() } } |
|
) |
|
// return the updated model + nested-model data |
|
.map { (index, $0) } |
|
} |
|
.take(8) |
|
.subscribe( |
|
onNext: { |
|
print("emit (model: v\($0.0), nested-model: v\($0.1))") |
|
} |
|
) |
|
|
|
// output: |
|
// |
|
// store:create model |
|
// store:create nested-model |
|
// emit (model: v0, nested-model: v0) |
|
// emit (model: v0, nested-model: v1) |
|
// emit (model: v0, nested-model: v2) |
|
// emit (model: v0, nested-model: v3) |
|
// store:reuse nested-model |
|
// emit (model: v1, nested-model: v3) |
|
// emit (model: v1, nested-model: v4) |
|
// emit (model: v1, nested-model: v5) |
|
// emit (model: v1, nested-model: v6) |
|
// store:remove model |
|
// store:remove nested-model |