使用 RxSwift 和 MVVM 处理错误

Handling error with RxSwift and MVVM

我正在尝试使用 RxSwift 和 MVVM 构建一个不错的架构。我想知道如何正确处理来自可观察对象的错误。

我的 ViewModel 看起来像:

class MapViewModel {

    private let disposeBag = DisposeBag()

    private let listObservable: Observable<[MyObject]>

    let list: Variable<[MyObject]>
    let showError: Variable<Bool>

    init() {
        self.listObservable = getObservable().shareReplay(1)

        self.list = Variable<[MyObject]>([])
        self.listObservable
            .bind(to: list)
            .addDisposableTo(self.disposeBag)

        self.showError = Variable<Bool>(false)
        self.listObservable
            .subscribe(
                onError: { [weak self] error in
                    print("Error downloading: \(error)")
                    self?.showError.value = true
            }).addDisposableTo(disposeBag)
    }
}

我认为这是正确的做法:明确分离关注点,并共享可观察对象以防止多次调用 REST 端点。

然而,当我这样做时——可观察对象发送了一个错误——我从 RxSwift 得到了一个 fatalError,因为错误没有在 bind() 调用中处理。

为了解决这个问题,我将代码更改为:

self.listObservable
    .subscribe(
        onNext: { [weak self] list in
            self?.list.value = list
        },
        onError: { [weak self] error in
            print("Error downloading: \(error)")
            self?.showError.value = true
    }).addDisposableTo(disposeBag)

这对我来说似乎不太清楚。正确的方法应该是什么?

我认为 Variables 的使用会让你失望。尽可能避免使用它们。

我对这段代码的印象:

  • 创建视图模型时,它会调用 getObservable()

  • 没有提供用户输入。

  • showError 变量似乎被用作触发器而不是实际传递值,因此它应该是 Void 而不是 Bool

我希望这个视图模型看起来更像:

struct MapViewModel {
    let list: Observable<[MyObject]>
    let showError: Observable<Void>

    init() {
        let dataResult = getObservable()
            .materialize()
            .shareReplayLatestWhileConnected()
        list = dataResult.map { [=10=].element }
            .filter { [=10=] != nil }
            .map { [=10=]! }
        showError = dataResult.map { [=10=].error }
            .filter { [=10=] != nil }
            .map { _ in }
    }
}

上面的秘诀是使用 materialize 将错误转换为 onNext 事件,以便您可以将其用于触发器。

subscribes/binds 和 dispose 包应该在视图控制器中,而不是在视图模型中。