_remember specification
This is the engineering specification for the MotionObservable
operator: _remember
.
Overview
_remember
caches the most recent upstream value and synchronously broadcasts it to all subscribers.
MVP
Expose _remember API
class MotionObservable<T> {
public func _remember() -> MotionObservable<T>
Create storage for a set of observers
public func _remember() -> MotionObservable<T> {
var observers: [MotionObserver<T>] = []
Create a nullable Subscription variable
Maintain a single upstream subscription so long as there is at least one downstream subscription.
public func _remember() -> MotionObservable<T> {
...
var subscription: Subscription?
Create a cache of the last-received value
This variable will store the last-received upstream value. This is necessary when providing the latest value to new subscribers.
public func _remember() -> MotionObservable<T> {
...
var lastValue: T?
Return a MotionObservable of type T
public func _remember() -> MotionObservable<T> {
...
return MotionObservable<T> {
// Connection logic
return {
// Disconnection logic
}
}
}
On connection: subscribe upstream if necessary
The subscription should cache the received value and emit the value to all subscribed observers.
public func _remember() -> MotionObservable<T> {
...
return MotionObservable<T> {
if observers.count == 0 {
subscription = self.subscribe { value in
lastValue = value
for observer in observers {
observer.next(value)
}
}
}
...
}
}
On connection: add the observer to the list of observers
This should be done after subscribing upstream.
public func _remember() -> MotionObservable<T> {
...
return MotionObservable<T> {
...
observers.append(observer)
...
}
}
On connection: immediately emit the last value to the observer
Only do this if lastValue has been set by the upstream subscription.
public func _remember() -> MotionObservable<T> {
...
return MotionObservable<T> {
...
if let lastValue = lastValue {
observer.next(lastValue)
}
...
}
}
On disconnection: remove the observer and unsubscribe if necessary
Unsubscribe once there are no more downstream subscribers.
public func _remember() -> MotionObservable<T> {
...
return MotionObservable<T> {
...
return {
if let index = observers.index(where: { $0 === observer }) {
observers.remove(at: index)
if observers.count == 0 {
subscription?.unsubscribe()
subscription = nil
}
}
}
}
}