【发布时间】:2022-07-09 13:43:46
【问题描述】:
我是一位经验丰富的 RxSwift 用户,并且在 RxSwift 中有一个很好的工作 MVVM 结构。我是Combine 的新手,但看在上帝的份上,我无法弄清楚如何在Combine 中做类似的事情。最大的障碍是组合中的 bind(to:) 等效项。我不知道如何将 1 个变量的结果链接到另一个变量。
这是我在 RxSwift 中要做的:
protocol UseCase {
func execute(id: Int) -> Single<CustomClass>
}
class DefaultUseCase: UseCase {
func execute(id: Int) -> Single<CustomClass> {
// Do network call and return in Single format
}
}
class ViewModel {
struct Input {
let load = PublishRelay<Void>()
}
struct Output {
let isButtonEnabled: Driver<Bool>
}
let disposeBag = DisposeBag()
let input = Input()
let output: Output
init(id: Int, useCase: UseCase = DefaultUseCase()) {
let isButtonEnabled = BehaviorRelay<Bool>(value: false)
let action = Action<Void, CustomClass> { id in
return useCase.execute(id: id)
}
self.output = Output(isButtonEnabled: isButtonEnabled.asDriver())
input
.load
.bind(to: useCase.inputs)
.disposed(by: disposeBag)
action
.elements
.map { // map CustomClass to Bool }
.bind(to: isButtonEnabled)
.disposed(by: disposeBag)
}
}
动作类来自这个框架:https://github.com/RxSwiftCommunity/Action
我不知道如何在 Combine 中做类似的事情,我已经阅读了一些教程,但这对我来说没有意义。看起来您需要感觉像一千个变量才能使用 viewModel 将 1 个值传递给您的视图/视图控制器。
我正在寻找一段与上面的 RxSwift 代码完全相同的代码,但在结合一些解释。
【问题讨论】:
-
所以看起来最大的障碍是
bind(to:)等价,建议在问题中更清楚地说明这一点,它会增加你得到回复的机会。 -
感谢@Cristik,不知道这并不完全清楚。将编辑问题!
-
它混淆了事件的来源。如果你有一个 Observable 链
a->b->c,那么就有明确的源到汇关系。事件流经从a到c的链。但是,如果这些元素中的每一个都是主题或中继,那么事件可以插入到链中的任何点,并且是对范式本质的诅咒。 -
“主题 [和中继] 提供了一种方便的方式来探索 Rx,但不建议将它们用于日常使用。” -- Intro to Rx
-
“函数式反应式编程的本质是在声明时完全指定一个值的动态行为。” -- Heinrich Apfelmus 主题和中继无视这一点。它们对于转换非响应式代码和处理反馈循环是必要的,但不应该是您解决问题的第一件事。
标签: swift mvvm rx-swift combine