rx-swift - RxSwift 变量到另一个变量的链式传播
问题描述
这是我们用例的一个例子:
我们有一个selectedIndex
和 的列表items
。
class FoosViewModel {
let selectedIndex = Variable<Int>(0)
let items: [Foo] = ... // assume that this is initialized properly
}
现实中,我们经常关心的是选中了哪个item,而不是被选中item的index。所以我们会有这样的代码:
selectedIndex.asObservable().subscribe(onNext: { [weak self] index in
guard let self = self else { return }
let selectedItem = items[index]
// Do sth with `selectedItem` here
}
请注意, 的值selectedItem
始终由 驱动selectedIndex
。因此,我们将代码更改为以下内容:
class FoosViewModel {
let selectedIndex = Variable<Int>(0)
let selectedItem = Variable<Int>(items[0])
let items: [Foo] = ... // assume that this is initialized properly
init() {
selectedIndex.asObservable().subscribe(onNext: { [weak self] index in
guard let self = self else { return }
self.selectedItem = items[index]
}
}
}
这似乎是一个足够常见的用例。我们在 Rx 中是否有一个可以将 a 映射Variable
到另一个的现有运算符?有没有这样的:
class FoosViewModel {
let selectedIndex = Variable<Int>(0)
let selectedItem = selectedIndex.map{ items[$0] }
let items: [Foo] = ... // assume that this is initialized properly
}
解决方案
您所做的是创建了两个相互依赖的状态。最好只有一个事实来源和一个衍生品,这意味着应该以不同于另一个的方式实施。假设这selectedIndex
是事实的来源,那么我希望看到:
class FoosViewModel {
let selectedIndex = Variable<Int>(0)
let selectedItem: Observable<Foo?>
let items: [Foo]
init(items: [Foo]) {
selectedItem = selectedIndex.asObservable().map { index in
index < items.count ? items[$0] : nil
}
self.items = items
}
}
与您的尝试不同,此类用户不会尝试分配新值selectedItem
(事实上,如果您尝试,代码甚至不会编译。)作为一个附带好处,没有必要这样做“弱自我舞蹈”要么因为地图根本没有提到self
。所有这些都有效,因为你做items
了一个 let 而不是 var (对你有好处!)
如果您希望能够添加/删除项目,那么事情会变得更加复杂......
class MutableFooViewModel {
let selectedIndex = Variable<Int>(0)
let selectedItem: Observable<Foo?>
let items = Variable<[Foo]>([])
init(items: [Foo]) {
items.value = items
let _items = self.items // this is done to avoid reference to `self` in the below.
selectedItem = Observable.combineLatest(
_items.asObservable(),
selectedIndex.asObservable()
) { items, index in
index < items.count ? items[index] : nil
}
}
}
这里的想法是,在制作依赖于其他可观察对象的可观察对象时,主题(变量是一种主题)不应该是您首先想到的。在这方面,它们仅适用于创建初始可观察对象。(RxCocoa 充满了它们。)
哦,顺便说一句,Variable
已被弃用。
推荐阅读
- react-native - 在 React Native 中嵌入 Instagram 帖子
- android - Dagger 2 获得自己的 Room 实例
- python - 如何修复“TypeError:+ 的不支持的操作数类型:'int' 和 'NoneType'”
- reactjs - 创建反应应用程序:配置笑话:运行所有测试文件
- javascript - 如何在jQuery中添加悬停文本?
- java - 哈希映射允许空插入但哈希表不允许空插入?
- java - 如何从 Coldfusion 2016 中加载 jsoup Java 库?
- makefile - makefile 可以在不先构建所有内容的情况下说“构建目标 X 和依赖它的所有内容”吗?
- java - 我将如何在我的代码中使用 SwitchMap (RXJAVA)?
- powerbi - 通过电子邮件向内部团队(分发组)发送 Power BI 报告