rx 的实现提供了BehaviorSubject<T>
和Variable<T>
作为建模随时间变化的属性的机制(C# INotifyPropertyChanged 的有用替代品)。
通常,这些属性显示为Observable<T>
但将属性公开为以下内容会更有用:
class ObservableValue<T> : Observable<T>{
var currentValue:T { get }
}
这可以沿着这些行在 swift 中创建:
class ObservableValue<Element> : ObservableType {
typealias E = Element
private let subject:BehaviorSubject<E>
var currentValue:E {
get {
return try! subject.value()
}
}
init(subject:BehaviorSubject<E>) {
self.subject = subject
}
func subscribe<O: ObserverType where O.E == E>(observer: O) -> Disposable {
return self.subject.subscribe(observer)
}
}
这已经存在了吗? 如果不是,是因为它违背了 Rx 的目标吗?
解决它的唯一方法是公开一个单独的currentValue或编写消费者,假设暴露的Observable背后的具体实现是行为主体或链中的某个地方发生了重播(),例如以下代码片段没有明确表示一旦我订阅,我就会得到一个值:
class MyViewModel {
// 'I will notify you of changes perhaps including my current value'
myProperty:Observable<String>
}
因此,代码必须编写得好像它与基本假设"异步"一样,它将以几乎同步的方式运行,而不是:
class MyViewModel {
// 'I have a current value and will notify you of changes going forward'
myProperty:ObservableValue<String>
}
经过深思熟虑并进行了更多的讨论,大概它不存在(也许不应该存在)的原因是它是对命令式访问状态的引入。
其他维护状态的机制(如scan
)是在链式可观察量范围内进行的,而不是作为"死胡同"的直接调用,如"现在给我价值"。
也许它会在混合反应式/命令式方法中占有一席之地,但它可能只会阻碍对反应式风格的完全接受。
这类似于在一半的代码中使用承诺或任务,然后在其他部分中恢复为同步阻塞代码。
在大多数情况下,人们所做的是创建一个标准视图模型,该模型通过 INotifyPropertyChanged 公开属性。这允许 UI 元素绑定到它们并接收属性更改事件并保持 UI 同步。
然后,如果您想要所述属性的 IObservable,您可以利用将事件转换为 IObservable 的标准 Rx 运算符。你可以谷歌这个找到很多不同的实现。您通常会从观察视图模型的内容中创建和使用这些可观察量,而不是直接在视图模型上公开它们。